100x-sdk 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,122 +8,122 @@ const JSONbig = require('json-bigint')({ storeAsString: false });
8
8
  /**
9
9
  * Simulate long position stop loss calculation
10
10
  *
11
- * 模拟做多仓位的止损计算,返回可执行的止损价格和相关参数。
12
- * 该函数会自动调整止损价格以避免与现有订单的价格区间重叠,
13
- * 并返回合约执行时需要的插入位置索引数组。
11
+ * Simulates the stop loss calculation for a long position, returning the executable stop loss price and related parameters.
12
+ * This function automatically adjusts the stop loss price to avoid overlapping with the price ranges of existing orders,
13
+ * and returns the insertion position index array required for contract execution.
14
14
  *
15
- * @param {string} mint - Token address / 代币地址
16
- * @param {bigint|string|number} buyTokenAmount - Token amount to buy for long position (u64 format, precision 10^9) / 做多买入的代币数量 (u64格式, 精度 10^9)
17
- * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format) / 用户期望的止损价格 (u128格式)
18
- * @param {Object|null} lastPrice - Token info, default null / 代币当前价格信息,默认null会自动获取
19
- * @param {Object|null} ordersData - Orders data, default null / 订单数据,默认null会自动获取
20
- * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%) / 借贷手续费率,默认2000 (2000/100000 = 0.02%)
15
+ * @param {string} mint - Token address
16
+ * @param {bigint|string|number} buyTokenAmount - Token amount to buy for long position (u64 format, precision 10^9)
17
+ * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format)
18
+ * @param {Object|null} lastPrice - Token info, default null (auto-fetched if null)
19
+ * @param {Object|null} ordersData - Orders data, default null (auto-fetched if null)
20
+ * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
21
21
  *
22
- * @returns {Promise<Object>} Stop loss analysis result / 止损分析结果对象
23
- * @returns {bigint} returns.executableStopLossPrice - 计算出的可执行止损价格 (u128格式)
24
- * - 这是经过调整后不与现有订单重叠的止损价格
25
- * - 可能低于用户输入的 stopLossPrice (因为需要避免重叠)
26
- * - 可以直接用于调用 sdk.trading.long() 的 closePrice 参数
22
+ * @returns {Promise<Object>} Stop loss analysis result
23
+ * @returns {bigint} returns.executableStopLossPrice - Calculated executable stop loss price (u128 format)
24
+ * - This is the stop loss price adjusted to not overlap with existing orders
25
+ * - May be lower than the user-provided stopLossPrice (to avoid overlap)
26
+ * - Can be used directly as the closePrice parameter of sdk.trading.long()
27
27
  *
28
- * @returns {bigint} returns.tradeAmount - 止损时预计卖出获得的SOL数量 (lamports)
29
- * - 这是在 executableStopLossPrice 价格卖出 buyTokenAmount 代币能获得的SOL
30
- * - 不包含手续费扣除
31
- * - 用于估算止损时的收益
28
+ * @returns {bigint} returns.tradeAmount - Estimated SOL amount obtained from selling at stop loss (lamports)
29
+ * - This is the SOL obtained from selling buyTokenAmount tokens at the executableStopLossPrice
30
+ * - Does not include fee deduction
31
+ * - Used to estimate the proceeds at stop loss
32
32
  *
33
- * @returns {number} returns.stopLossPercentage - 止损百分比 (相对于当前价格)
34
- * - 计算公式: ((currentPrice - executableStopLossPrice) / currentPrice) * 100
35
- * - 例如: 3.5 表示止损价格比当前价格低3.5%
36
- * - 做多时这个值应该是正数 (止损价低于当前价)
33
+ * @returns {number} returns.stopLossPercentage - Stop loss percentage (relative to current price)
34
+ * - Formula: ((currentPrice - executableStopLossPrice) / currentPrice) * 100
35
+ * - For example: 3.5 means the stop loss price is 3.5% lower than the current price
36
+ * - For a long position this value should be positive (stop loss price below current price)
37
37
  *
38
- * @returns {number} returns.leverage - 杠杆倍数
39
- * - 计算公式: currentPrice / (currentPrice - executableStopLossPrice)
40
- * - 例如: 28.57 表示约28.57倍杠杆
41
- * - 杠杆越高,风险越大,但潜在收益也越大
38
+ * @returns {number} returns.leverage - Leverage ratio
39
+ * - Formula: currentPrice / (currentPrice - executableStopLossPrice)
40
+ * - For example: 28.57 means about 28.57x leverage
41
+ * - The higher the leverage, the higher the risk, but also the higher the potential return
42
42
  *
43
- * @returns {bigint} returns.currentPrice - 当前价格 (u128格式)
44
- * - 计算时使用的代币当前价格
45
- * - 用于参考和验证
43
+ * @returns {bigint} returns.currentPrice - Current price (u128 format)
44
+ * - The current token price used in the calculation
45
+ * - Used for reference and validation
46
46
  *
47
- * @returns {number} returns.iterations - 价格调整迭代次数
48
- * - 为了避免价格区间重叠,函数自动调整止损价格的次数
49
- * - 每次调整会将价格降低 PRICE_ADJUSTMENT_PERCENTAGE (默认0.5%)
50
- * - 如果迭代次数过高,可能需要重新选择止损价格
47
+ * @returns {number} returns.iterations - Number of price adjustment iterations
48
+ * - The number of times the function automatically adjusted the stop loss price to avoid price range overlap
49
+ * - Each adjustment lowers the price by PRICE_ADJUSTMENT_PERCENTAGE (default 0.5%)
50
+ * - If the iteration count is too high, you may need to reselect the stop loss price
51
51
  *
52
- * @returns {bigint} returns.originalStopLossPrice - 用户输入的原始止损价格 (u128格式)
53
- * - 用于对比调整前后的价格差异
54
- * - 如果 executableStopLossPrice 与此差异较大,说明现有订单较密集
52
+ * @returns {bigint} returns.originalStopLossPrice - User-provided original stop loss price (u128 format)
53
+ * - Used to compare the price difference before and after adjustment
54
+ * - If executableStopLossPrice differs greatly from this, it indicates existing orders are dense
55
55
  *
56
- * @returns {number[]} returns.close_insert_indices - 平仓订单插入位置的候选索引数组 ⭐ 新增
57
- * - 数组包含多个候选插入位置的 OrderBook 索引值
58
- * - 结构: [主位置index, 前1个index, 后1个index, 前2个index, 后2个index, 前3个index, 后3个index]
59
- * - 例如: [25, 10, 33, 5, 40, 2, 50] 表示主位置是索引25,备选位置包括索引10、33等
60
- * - 最多包含7个索引值 (1个主位置 + 前3个 + 后3个)
61
- * - 如果订单簿为空,返回 [65535] (u16::MAX,表示插入到头部)
62
- * - 用途: 传递给 sdk.trading.long() 的 closeInsertIndices 参数
63
- * - 提高成功率: 即使主位置的订单被删除,合约也能尝试其他候选位置
56
+ * @returns {number[]} returns.close_insert_indices - Candidate index array for the closing order insertion position ⭐ New
57
+ * - The array contains the OrderBook index values of multiple candidate insertion positions
58
+ * - Structure: [main position index, 1st before, 1st after, 2nd before, 2nd after, 3rd before, 3rd after]
59
+ * - For example: [25, 10, 33, 5, 40, 2, 50] means the main position is index 25, with alternative positions including indices 10, 33, etc.
60
+ * - Contains up to 7 index values (1 main position + 3 before + 3 after)
61
+ * - If the orderbook is empty, returns [65535] (u16::MAX, meaning insert at the head)
62
+ * - Usage: passed as the closeInsertIndices parameter of sdk.trading.long()
63
+ * - Improves success rate: even if the order at the main position is deleted, the contract can try other candidate positions
64
64
  *
65
- * @returns {bigint} returns.estimatedMargin - 预估所需保证金 (SOL lamports)
66
- * - 计算公式: 买入成本 - 平仓收益(扣除手续费后)
67
- * - 这是执行此止损策略需要的最少保证金
68
- * - 可以用于 sdk.trading.long() 的 marginSolMax 参数
69
- * - 实际调用时建议增加10-20%余量以应对价格波动
65
+ * @returns {bigint} returns.estimatedMargin - Estimated required margin (SOL lamports)
66
+ * - Formula: buy cost - close proceeds (after fee deduction)
67
+ * - This is the minimum margin required to execute this stop loss strategy
68
+ * - Can be used as the marginSolMax parameter of sdk.trading.long()
69
+ * - When actually calling, it is recommended to add a 10-20% buffer to handle price fluctuations
70
70
  *
71
- * @throws {Error} 当缺少必需参数时
72
- * @throws {Error} 当无法获取价格或订单数据时
73
- * @throws {Error} 当达到最大迭代次数仍无法找到合适的止损价格时
74
- * @throws {Error} 当价格调整后变为负数时
71
+ * @throws {Error} When required parameters are missing
72
+ * @throws {Error} When price or orders data cannot be fetched
73
+ * @throws {Error} When a suitable stop loss price cannot be found after reaching the maximum iterations
74
+ * @throws {Error} When the price becomes negative after adjustment
75
75
  *
76
76
  * @example
77
- * // 基础用法: 做多1个代币,止损价格为当前价格的97%
77
+ * // Basic usage: long 1 token, stop loss price at 97% of the current price
78
78
  * const result = await sdk.simulator.simulateLongStopLoss(
79
79
  * '4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X', // mint
80
- * 1000000000n, // 1 token (精度10^9)
81
- * BigInt('97000000000000000000') // 止损价格
80
+ * 1000000000n, // 1 token (precision 10^9)
81
+ * BigInt('97000000000000000000') // stop loss price
82
82
  * );
83
83
  *
84
- * console.log(`可执行止损价格: ${result.executableStopLossPrice}`);
85
- * console.log(`止损百分比: ${result.stopLossPercentage}%`);
86
- * console.log(`杠杆倍数: ${result.leverage}x`);
87
- * console.log(`预估保证金: ${result.estimatedMargin} lamports`);
88
- * console.log(`插入位置索引: ${result.close_insert_indices}`);
84
+ * console.log(`Executable stop loss price: ${result.executableStopLossPrice}`);
85
+ * console.log(`Stop loss percentage: ${result.stopLossPercentage}%`);
86
+ * console.log(`Leverage: ${result.leverage}x`);
87
+ * console.log(`Estimated margin: ${result.estimatedMargin} lamports`);
88
+ * console.log(`Insert position indices: ${result.close_insert_indices}`);
89
89
  *
90
90
  * @example
91
- * // 完整使用流程: 模拟后执行做多交易
91
+ * // Full workflow: simulate then execute a long trade
92
92
  * async function openLongPosition(sdk, mint, buyTokenAmount, stopLossPrice) {
93
- * // 1. 模拟止损计算
93
+ * // 1. Simulate stop loss calculation
94
94
  * const simulation = await sdk.simulator.simulateLongStopLoss(
95
95
  * mint,
96
96
  * buyTokenAmount,
97
97
  * stopLossPrice
98
98
  * );
99
99
  *
100
- * // 2. 检查止损价格是否被大幅调整
100
+ * // 2. Check whether the stop loss price was significantly adjusted
101
101
  * const priceDiff = Number((simulation.originalStopLossPrice - simulation.executableStopLossPrice) * 10000n / simulation.originalStopLossPrice) / 100;
102
102
  * if (priceDiff > 1.0) {
103
- * console.warn(`止损价格被调整了 ${priceDiff}%, 当前订单较密集`);
103
+ * console.warn(`Stop loss price was adjusted by ${priceDiff}%, existing orders are dense`);
104
104
  * }
105
105
  *
106
- * // 3. 准备交易参数
107
- * const maxSolAmount = simulation.estimatedMargin * 120n / 100n; // 增加20%余量
108
- * const marginSolMax = simulation.estimatedMargin * 115n / 100n; // 增加15%余量
106
+ * // 3. Prepare transaction parameters
107
+ * const maxSolAmount = simulation.estimatedMargin * 120n / 100n; // add 20% buffer
108
+ * const marginSolMax = simulation.estimatedMargin * 115n / 100n; // add 15% buffer
109
109
  *
110
- * // 4. 执行做多交易
110
+ * // 4. Execute the long trade
111
111
  * const tx = await sdk.trading.long({
112
112
  * mint: mint,
113
113
  * buyTokenAmount: buyTokenAmount,
114
114
  * maxSolAmount: maxSolAmount,
115
115
  * marginSolMax: marginSolMax,
116
116
  * closePrice: simulation.executableStopLossPrice,
117
- * closeInsertIndices: simulation.close_insert_indices // ⭐ 使用新的索引数组
117
+ * closeInsertIndices: simulation.close_insert_indices // ⭐ use the new index array
118
118
  * });
119
119
  *
120
120
  * return tx;
121
121
  * }
122
122
  *
123
- * @see {@link simulateShortStopLoss} 做空仓位的止损计算
124
- * @see {@link simulateLongSolStopLoss} 基于SOL金额的做多止损计算
123
+ * @see {@link simulateShortStopLoss} Stop loss calculation for short positions
124
+ * @see {@link simulateLongSolStopLoss} SOL-amount-based stop loss calculation for long positions
125
125
  * @since 2.0.0
126
- * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
126
+ * @version 2.0.0 - Changed from returning prev_order_pda/next_order_pda to returning close_insert_indices
127
127
  */
128
128
  async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
129
129
  try {
@@ -132,12 +132,12 @@ async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPri
132
132
  throw new Error('Missing required parameters');
133
133
  }
134
134
 
135
- // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
135
+ // If borrowFee or pool parameters are not provided, fetch them from the chain in a single call
136
136
  if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
137
137
  const curveAccount = await this.sdk.chain.getCurveAccount(mint, { skipBalances: true });
138
138
  if (borrowFee === null) borrowFee = curveAccount.borrowFee;
139
- // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
140
- // 与 calcLiq.js 中的转换方式一致
139
+ // The chain returns u64 raw units (lamports/smallest unit), which need to be divided by 10^9 to convert to human-readable units
140
+ // Consistent with the conversion method in calcLiq.js
141
141
  if (initialVirtualSol === null) initialVirtualSol = new Decimal(curveAccount.initialVirtualSol.toString()).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL).toString();
142
142
  if (initialVirtualToken === null) initialVirtualToken = new Decimal(curveAccount.initialVirtualToken.toString()).div(CurveAMM.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
143
143
  }
@@ -191,7 +191,7 @@ async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPri
191
191
  let finalOverlapResult = null; // Record final overlap result
192
192
  let finalTradeAmount = 0n; // Record final trade amount
193
193
 
194
- // 检查并调整止损价格以满足最小距离要求 (做多: 止损价必须低于当前价至少 MIN_STOP_LOSS_PERCENT)
194
+ // Check and adjust the stop loss price to meet the minimum distance requirement (long: stop loss price must be below current price by at least MIN_STOP_LOSS_PERCENT)
195
195
  // Check and adjust stop loss price to meet minimum distance requirement (long: stop loss must be below current price by at least MIN_STOP_LOSS_PERCENT)
196
196
  const minAllowedStopLoss = currentPrice - (currentPrice * BigInt(MIN_STOP_LOSS_PERCENT)) / 1000n;
197
197
  if (stopLossStartPrice > minAllowedStopLoss) {
@@ -230,33 +230,33 @@ async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPri
230
230
  }
231
231
 
232
232
  stopLossEndPrice = tradeResult[0]; // Price after trade completion
233
- const tradeAmount = tradeResult[1]; // SOL输出量 / SOL output amount
233
+ const tradeAmount = tradeResult[1]; // SOL output amount
234
234
 
235
235
  // console.log(` - stopLossEndPrice: ${stopLossEndPrice.toString()}`);
236
236
  // console.log(` - tradeAmount: ${tradeAmount.toString()}`);
237
237
 
238
- //console.log(`迭代 ${iteration}: 起始价格=${stopLossStartPrice}, 结束价格=${stopLossEndPrice}, SOL输出量=${tradeAmount} / Iteration ${iteration}: Start=${stopLossStartPrice}, End=${stopLossEndPrice}, SOL output=${tradeAmount}`);
238
+ //console.log(`Iteration ${iteration}: startPrice=${stopLossStartPrice}, endPrice=${stopLossEndPrice}, SOL output=${tradeAmount} / Iteration ${iteration}: Start=${stopLossStartPrice}, End=${stopLossEndPrice}, SOL output=${tradeAmount}`);
239
239
 
240
- // 检查价格区间重叠 / Check price range overlap
240
+ // Check price range overlap
241
241
  const overlapResult = checkPriceRangeOverlap('down_orders', downOrders, stopLossStartPrice, stopLossEndPrice);
242
-
242
+
243
243
  if (overlapResult.no_overlap) {
244
- //console.log('价格区间无重叠,可以执行 / No price range overlap, can execute');
245
- finalOverlapResult = overlapResult; // 记录最终的overlap结果 / Record final overlap result
246
- finalTradeAmount = tradeAmount; // 记录最终的交易金额 / Record final trade amount
244
+ //console.log('No price range overlap, can execute / No price range overlap, can execute');
245
+ finalOverlapResult = overlapResult; // Record final overlap result
246
+ finalTradeAmount = tradeAmount; // Record final trade amount
247
247
  break;
248
248
  }
249
249
 
250
- //console.log(`发现重叠: ${overlapResult.overlap_reason} / Found overlap: ${overlapResult.overlap_reason}`);
250
+ //console.log(`Found overlap: ${overlapResult.overlap_reason} / Found overlap: ${overlapResult.overlap_reason}`);
251
251
 
252
- // 调整起始价格(减少0.5%)/ Adjust start price (decrease by 0.5%)
253
- // 使用方案2:直接计算 0.5% = 5/1000
252
+ // Adjust start price (decrease by 0.5%)
253
+ // Using approach 2: directly compute 0.5% = 5/1000
254
254
  const adjustmentAmount = (stopLossStartPrice * BigInt(PRICE_ADJUSTMENT_PERCENTAGE)) / 1000n;
255
255
  stopLossStartPrice = stopLossStartPrice - adjustmentAmount;
256
256
 
257
- //console.log(`调整后起始价格: ${stopLossStartPrice} / Adjusted start price: ${stopLossStartPrice}`);
257
+ //console.log(`Adjusted start price: ${stopLossStartPrice} / Adjusted start price: ${stopLossStartPrice}`);
258
258
 
259
- // 安全检查:确保价格不会变成负数 / Safety check: ensure price doesn't become negative
259
+ // Safety check: ensure the price does not become negative
260
260
  if (stopLossStartPrice <= 0n) {
261
261
  throw new Error('止损价格调整后变为负数,无法继续 / Stop loss price became negative after adjustment');
262
262
  }
@@ -266,30 +266,30 @@ async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPri
266
266
  throw new Error('达到最大迭代次数,无法找到合适的止损价格 / Reached maximum iterations, cannot find suitable stop loss price');
267
267
  }
268
268
 
269
- // 计算最终返回值 / Calculate final return values
269
+ // Calculate final return values
270
270
  const executableStopLossPrice = stopLossStartPrice;
271
-
272
- // 计算止损百分比 / Calculate stop loss percentage
271
+
272
+ // Calculate stop loss percentage
273
273
  let stopLossPercentage = 0;
274
274
  let leverage = 1;
275
-
275
+
276
276
  if (currentPrice !== executableStopLossPrice) {
277
277
  stopLossPercentage = Number((BigInt(10000) * (currentPrice - executableStopLossPrice)) / currentPrice) / 100;
278
278
  leverage = Number((BigInt(10000) * currentPrice) / (currentPrice - executableStopLossPrice)) / 10000;
279
279
  }
280
280
 
281
- // 计算保证金 / Calculate margin requirement
281
+ // Calculate margin requirement
282
282
  let estimatedMargin = 0n;
283
283
  try {
284
- // 1. 计算从当前价格买入所需的SOL
284
+ // 1. Calculate the SOL required to buy from the current price
285
285
  const buyResult = CurveAMM.buyFromPriceWithTokenOutputWithParams(currentPrice, buyTokenAmount, initialVirtualSol, initialVirtualToken);
286
286
  if (buyResult) {
287
287
  const requiredSol = buyResult[1]; // SOL input amount
288
288
 
289
- // 2. 计算平仓时扣除手续费后的收益
289
+ // 2. Calculate the proceeds at close after deducting the fee
290
290
  const closeOutputSolAfterFee = CurveAMM.calculateAmountAfterFee(finalTradeAmount, borrowFee);
291
-
292
- // 3. 计算保证金 = 买入成本 - 平仓收益(扣费后)
291
+
292
+ // 3. Calculate margin = buy cost - close proceeds (after fee deduction)
293
293
  if (closeOutputSolAfterFee !== null && requiredSol > closeOutputSolAfterFee) {
294
294
  estimatedMargin = requiredSol - closeOutputSolAfterFee;
295
295
  }
@@ -328,122 +328,122 @@ async function simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPri
328
328
  /**
329
329
  * Simulate short position stop loss calculation
330
330
  *
331
- * 模拟做空仓位的止损计算,返回可执行的止损价格和相关参数。
332
- * 该函数会自动调整止损价格以避免与现有订单的价格区间重叠,
333
- * 并返回合约执行时需要的插入位置索引数组。
331
+ * Simulates the stop loss calculation for a short position, returning the executable stop loss price and related parameters.
332
+ * This function automatically adjusts the stop loss price to avoid overlapping with the price ranges of existing orders,
333
+ * and returns the insertion position index array required for contract execution.
334
334
  *
335
- * @param {string} mint - Token address / 代币地址
336
- * @param {bigint|string|number} sellTokenAmount - Token amount to sell for short position (u64 format, precision 10^9) / 做空卖出的代币数量 (u64格式, 精度 10^9)
337
- * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format) / 用户期望的止损价格 (u128格式)
338
- * @param {Object|null} lastPrice - Token info, default null / 代币当前价格信息,默认null会自动获取
339
- * @param {Object|null} ordersData - Orders data, default null / 订单数据,默认null会自动获取
340
- * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%) / 借贷手续费率,默认2000 (2000/100000 = 0.02%)
335
+ * @param {string} mint - Token address
336
+ * @param {bigint|string|number} sellTokenAmount - Token amount to sell for short position (u64 format, precision 10^9)
337
+ * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format)
338
+ * @param {Object|null} lastPrice - Token info, default null (auto-fetched if null)
339
+ * @param {Object|null} ordersData - Orders data, default null (auto-fetched if null)
340
+ * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
341
341
  *
342
- * @returns {Promise<Object>} Stop loss analysis result / 止损分析结果对象
343
- * @returns {bigint} returns.executableStopLossPrice - 计算出的可执行止损价格 (u128格式)
344
- * - 这是经过调整后不与现有订单重叠的止损价格
345
- * - 可能高于用户输入的 stopLossPrice (因为需要避免重叠)
346
- * - 可以直接用于调用 sdk.trading.short() 的 closePrice 参数
342
+ * @returns {Promise<Object>} Stop loss analysis result
343
+ * @returns {bigint} returns.executableStopLossPrice - Calculated executable stop loss price (u128 format)
344
+ * - This is the stop loss price adjusted to not overlap with existing orders
345
+ * - May be higher than the user-provided stopLossPrice (to avoid overlap)
346
+ * - Can be used directly as the closePrice parameter of sdk.trading.short()
347
347
  *
348
- * @returns {bigint} returns.tradeAmount - 止损时预计买入需要的SOL数量 (lamports)
349
- * - 这是在 executableStopLossPrice 价格买回 sellTokenAmount 代币需要的SOL
350
- * - 不包含手续费
351
- * - 用于估算止损时的成本
348
+ * @returns {bigint} returns.tradeAmount - Estimated SOL amount needed to buy back at stop loss (lamports)
349
+ * - This is the SOL needed to buy back sellTokenAmount tokens at the executableStopLossPrice
350
+ * - Does not include fees
351
+ * - Used to estimate the cost at stop loss
352
352
  *
353
- * @returns {number} returns.stopLossPercentage - 止损百分比 (相对于当前价格)
354
- * - 计算公式: ((executableStopLossPrice - currentPrice) / currentPrice) * 100
355
- * - 例如: 3.5 表示止损价格比当前价格高3.5%
356
- * - 做空时这个值应该是正数 (止损价高于当前价)
353
+ * @returns {number} returns.stopLossPercentage - Stop loss percentage (relative to current price)
354
+ * - Formula: ((executableStopLossPrice - currentPrice) / currentPrice) * 100
355
+ * - For example: 3.5 means the stop loss price is 3.5% higher than the current price
356
+ * - For a short position this value should be positive (stop loss price above current price)
357
357
  *
358
- * @returns {number} returns.leverage - 杠杆倍数
359
- * - 计算公式: currentPrice / (executableStopLossPrice - currentPrice)
360
- * - 例如: 28.57 表示约28.57倍杠杆
361
- * - 杠杆越高,风险越大,但潜在收益也越大
358
+ * @returns {number} returns.leverage - Leverage ratio
359
+ * - Formula: currentPrice / (executableStopLossPrice - currentPrice)
360
+ * - For example: 28.57 means about 28.57x leverage
361
+ * - The higher the leverage, the higher the risk, but also the higher the potential return
362
362
  *
363
- * @returns {bigint} returns.currentPrice - 当前价格 (u128格式)
364
- * - 计算时使用的代币当前价格
365
- * - 用于参考和验证
363
+ * @returns {bigint} returns.currentPrice - Current price (u128 format)
364
+ * - The current token price used in the calculation
365
+ * - Used for reference and validation
366
366
  *
367
- * @returns {number} returns.iterations - 价格调整迭代次数
368
- * - 为了避免价格区间重叠,函数自动调整止损价格的次数
369
- * - 每次调整会将价格提高 PRICE_ADJUSTMENT_PERCENTAGE (默认0.5%)
370
- * - 如果迭代次数过高,可能需要重新选择止损价格
367
+ * @returns {number} returns.iterations - Number of price adjustment iterations
368
+ * - The number of times the function automatically adjusted the stop loss price to avoid price range overlap
369
+ * - Each adjustment raises the price by PRICE_ADJUSTMENT_PERCENTAGE (default 0.5%)
370
+ * - If the iteration count is too high, you may need to reselect the stop loss price
371
371
  *
372
- * @returns {bigint} returns.originalStopLossPrice - 用户输入的原始止损价格 (u128格式)
373
- * - 用于对比调整前后的价格差异
374
- * - 如果 executableStopLossPrice 与此差异较大,说明现有订单较密集
372
+ * @returns {bigint} returns.originalStopLossPrice - User-provided original stop loss price (u128 format)
373
+ * - Used to compare the price difference before and after adjustment
374
+ * - If executableStopLossPrice differs greatly from this, it indicates existing orders are dense
375
375
  *
376
- * @returns {number[]} returns.close_insert_indices - 平仓订单插入位置的候选索引数组 ⭐ 新增
377
- * - 数组包含多个候选插入位置的 OrderBook 索引值
378
- * - 结构: [主位置index, 前1个index, 后1个index, 前2个index, 后2个index, 前3个index, 后3个index]
379
- * - 例如: [25, 10, 33, 5, 40, 2, 50] 表示主位置是索引25,备选位置包括索引10、33等
380
- * - 最多包含7个索引值 (1个主位置 + 前3个 + 后3个)
381
- * - 如果订单簿为空,返回 [65535] (u16::MAX,表示插入到头部)
382
- * - 用途: 传递给 sdk.trading.short() 的 closeInsertIndices 参数
383
- * - 提高成功率: 即使主位置的订单被删除,合约也能尝试其他候选位置
376
+ * @returns {number[]} returns.close_insert_indices - Candidate index array for the closing order insertion position ⭐ New
377
+ * - The array contains the OrderBook index values of multiple candidate insertion positions
378
+ * - Structure: [main position index, 1st before, 1st after, 2nd before, 2nd after, 3rd before, 3rd after]
379
+ * - For example: [25, 10, 33, 5, 40, 2, 50] means the main position is index 25, with alternative positions including indices 10, 33, etc.
380
+ * - Contains up to 7 index values (1 main position + 3 before + 3 after)
381
+ * - If the orderbook is empty, returns [65535] (u16::MAX, meaning insert at the head)
382
+ * - Usage: passed as the closeInsertIndices parameter of sdk.trading.short()
383
+ * - Improves success rate: even if the order at the main position is deleted, the contract can try other candidate positions
384
384
  *
385
- * @returns {bigint} returns.estimatedMargin - 预估所需保证金 (SOL lamports)
386
- * - 计算公式: 平仓成本(含手续费) - 开仓收益 - 开仓手续费
387
- * - 这是执行此止损策略需要的最少保证金
388
- * - 可以用于 sdk.trading.short() 的 marginSolMax 参数
389
- * - 实际调用时建议增加10-20%余量以应对价格波动
385
+ * @returns {bigint} returns.estimatedMargin - Estimated required margin (SOL lamports)
386
+ * - Formula: close cost (including fee) - open proceeds - open fee
387
+ * - This is the minimum margin required to execute this stop loss strategy
388
+ * - Can be used as the marginSolMax parameter of sdk.trading.short()
389
+ * - When actually calling, it is recommended to add a 10-20% buffer to handle price fluctuations
390
390
  *
391
- * @throws {Error} 当缺少必需参数时
392
- * @throws {Error} 当无法获取价格或订单数据时
393
- * @throws {Error} 当达到最大迭代次数仍无法找到合适的止损价格时
394
- * @throws {Error} 当价格调整后超过最大值时
391
+ * @throws {Error} When required parameters are missing
392
+ * @throws {Error} When price or orders data cannot be fetched
393
+ * @throws {Error} When a suitable stop loss price cannot be found after reaching the maximum iterations
394
+ * @throws {Error} When the price exceeds the maximum value after adjustment
395
395
  *
396
396
  * @example
397
- * // 基础用法: 做空1个代币,止损价格为当前价格的103%
397
+ * // Basic usage: short 1 token, stop loss price at 103% of the current price
398
398
  * const result = await sdk.simulator.simulateShortStopLoss(
399
399
  * '4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X', // mint
400
- * 1000000000n, // 1 token (精度10^9)
401
- * BigInt('103000000000000000000') // 止损价格
400
+ * 1000000000n, // 1 token (precision 10^9)
401
+ * BigInt('103000000000000000000') // stop loss price
402
402
  * );
403
403
  *
404
- * console.log(`可执行止损价格: ${result.executableStopLossPrice}`);
405
- * console.log(`止损百分比: ${result.stopLossPercentage}%`);
406
- * console.log(`杠杆倍数: ${result.leverage}x`);
407
- * console.log(`预估保证金: ${result.estimatedMargin} lamports`);
408
- * console.log(`插入位置索引: ${result.close_insert_indices}`);
404
+ * console.log(`Executable stop loss price: ${result.executableStopLossPrice}`);
405
+ * console.log(`Stop loss percentage: ${result.stopLossPercentage}%`);
406
+ * console.log(`Leverage: ${result.leverage}x`);
407
+ * console.log(`Estimated margin: ${result.estimatedMargin} lamports`);
408
+ * console.log(`Insert position indices: ${result.close_insert_indices}`);
409
409
  *
410
410
  * @example
411
- * // 完整使用流程: 模拟后执行做空交易
411
+ * // Full workflow: simulate then execute a short trade
412
412
  * async function openShortPosition(sdk, mint, sellTokenAmount, stopLossPrice) {
413
- * // 1. 模拟止损计算
413
+ * // 1. Simulate stop loss calculation
414
414
  * const simulation = await sdk.simulator.simulateShortStopLoss(
415
415
  * mint,
416
416
  * sellTokenAmount,
417
417
  * stopLossPrice
418
418
  * );
419
419
  *
420
- * // 2. 检查止损价格是否被大幅调整
420
+ * // 2. Check whether the stop loss price was significantly adjusted
421
421
  * const priceDiff = Number((simulation.executableStopLossPrice - simulation.originalStopLossPrice) * 10000n / simulation.originalStopLossPrice) / 100;
422
422
  * if (priceDiff > 1.0) {
423
- * console.warn(`止损价格被调整了 ${priceDiff}%, 当前订单较密集`);
423
+ * console.warn(`Stop loss price was adjusted by ${priceDiff}%, existing orders are dense`);
424
424
  * }
425
425
  *
426
- * // 3. 准备交易参数
427
- * const minSolOutput = simulation.tradeAmount * 80n / 100n; // 至少获得80%
428
- * const marginSolMax = simulation.estimatedMargin * 115n / 100n; // 增加15%余量
426
+ * // 3. Prepare transaction parameters
427
+ * const minSolOutput = simulation.tradeAmount * 80n / 100n; // obtain at least 80%
428
+ * const marginSolMax = simulation.estimatedMargin * 115n / 100n; // add 15% buffer
429
429
  *
430
- * // 4. 执行做空交易
430
+ * // 4. Execute the short trade
431
431
  * const tx = await sdk.trading.short({
432
432
  * mint: mint,
433
433
  * borrowSellTokenAmount: sellTokenAmount,
434
434
  * minSolOutput: minSolOutput,
435
435
  * marginSolMax: marginSolMax,
436
436
  * closePrice: simulation.executableStopLossPrice,
437
- * closeInsertIndices: simulation.close_insert_indices // ⭐ 使用新的索引数组
437
+ * closeInsertIndices: simulation.close_insert_indices // ⭐ use the new index array
438
438
  * });
439
439
  *
440
440
  * return tx;
441
441
  * }
442
442
  *
443
- * @see {@link simulateLongStopLoss} 做多仓位的止损计算
444
- * @see {@link simulateShortSolStopLoss} 基于SOL金额的做空止损计算
443
+ * @see {@link simulateLongStopLoss} Stop loss calculation for long positions
444
+ * @see {@link simulateShortSolStopLoss} SOL-amount-based stop loss calculation for short positions
445
445
  * @since 2.0.0
446
- * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
446
+ * @version 2.0.0 - Changed from returning prev_order_pda/next_order_pda to returning close_insert_indices
447
447
  */
448
448
  async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
449
449
  try {
@@ -452,12 +452,12 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
452
452
  throw new Error('Missing required parameters');
453
453
  }
454
454
 
455
- // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
455
+ // If borrowFee or pool parameters are not provided, fetch them from the chain in a single call
456
456
  if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
457
457
  const curveAccount = await this.sdk.chain.getCurveAccount(mint, { skipBalances: true });
458
458
  if (borrowFee === null) borrowFee = curveAccount.borrowFee;
459
- // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
460
- // 与 calcLiq.js 中的转换方式一致
459
+ // The chain returns u64 raw units (lamports/smallest unit), which need to be divided by 10^9 to convert to human-readable units
460
+ // Consistent with the conversion method in calcLiq.js
461
461
  if (initialVirtualSol === null) initialVirtualSol = new Decimal(curveAccount.initialVirtualSol.toString()).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL).toString();
462
462
  if (initialVirtualToken === null) initialVirtualToken = new Decimal(curveAccount.initialVirtualToken.toString()).div(CurveAMM.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
463
463
  }
@@ -508,7 +508,7 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
508
508
  let finalOverlapResult = null; // Record final overlap result
509
509
  let finalTradeAmount = 0n; // Record final trade amount
510
510
 
511
- // 检查并调整止损价格以满足最小距离要求 (做空: 止损价必须高于当前价至少 MIN_STOP_LOSS_PERCENT)
511
+ // Check and adjust the stop loss price to meet the minimum distance requirement (short: stop loss price must be above current price by at least MIN_STOP_LOSS_PERCENT)
512
512
  // Check and adjust stop loss price to meet minimum distance requirement (short: stop loss must be above current price by at least MIN_STOP_LOSS_PERCENT)
513
513
  const minAllowedStopLoss = currentPrice + (currentPrice * BigInt(MIN_STOP_LOSS_PERCENT)) / 1000n;
514
514
  if (stopLossStartPrice < minAllowedStopLoss) {
@@ -543,33 +543,33 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
543
543
  }
544
544
 
545
545
  stopLossEndPrice = tradeResult[0]; // Price after trade completion
546
- const tradeAmount = tradeResult[1]; // SOL输入量 / SOL input amount
546
+ const tradeAmount = tradeResult[1]; // SOL input amount
547
547
 
548
548
  // console.log(` - stopLossEndPrice: ${stopLossEndPrice.toString()}`);
549
549
  // console.log(` - tradeAmount: ${tradeAmount.toString()}`);
550
550
 
551
- //console.log(`迭代 ${iteration}: 起始价格=${stopLossStartPrice}, 结束价格=${stopLossEndPrice}, SOL输入量=${tradeAmount} / Iteration ${iteration}: Start=${stopLossStartPrice}, End=${stopLossEndPrice}, SOL input=${tradeAmount}`);
551
+ //console.log(`Iteration ${iteration}: startPrice=${stopLossStartPrice}, endPrice=${stopLossEndPrice}, SOL input=${tradeAmount} / Iteration ${iteration}: Start=${stopLossStartPrice}, End=${stopLossEndPrice}, SOL input=${tradeAmount}`);
552
552
 
553
- // 检查价格区间重叠 / Check price range overlap
553
+ // Check price range overlap
554
554
  const overlapResult = checkPriceRangeOverlap('up_orders', upOrders, stopLossStartPrice, stopLossEndPrice);
555
-
555
+
556
556
  if (overlapResult.no_overlap) {
557
557
  //console.log(' / No price range overlap, can execute');
558
- finalOverlapResult = overlapResult; // 记录最终的overlap结果 / Record final overlap result
559
- finalTradeAmount = tradeAmount; // 记录最终的交易金额 / Record final trade amount
558
+ finalOverlapResult = overlapResult; // Record final overlap result
559
+ finalTradeAmount = tradeAmount; // Record final trade amount
560
560
  break;
561
561
  }
562
562
 
563
- //console.log(`发现重叠: ${overlapResult.overlap_reason} / Found overlap: ${overlapResult.overlap_reason}`);
563
+ //console.log(`Found overlap: ${overlapResult.overlap_reason} / Found overlap: ${overlapResult.overlap_reason}`);
564
564
 
565
- // 调整起始价格(增加0.5%)/ Adjust start price (increase by 0.5%)
566
- // 使用方案2:直接计算 0.5% = 5/1000
565
+ // Adjust start price (increase by 0.5%)
566
+ // Using approach 2: directly compute 0.5% = 5/1000
567
567
  const adjustmentAmount = (stopLossStartPrice * BigInt(PRICE_ADJUSTMENT_PERCENTAGE)) / 1000n;
568
568
  stopLossStartPrice = stopLossStartPrice + adjustmentAmount;
569
569
 
570
- //console.log(`调整后起始价格: ${stopLossStartPrice} / Adjusted start price: ${stopLossStartPrice}`);
570
+ //console.log(`Adjusted start price: ${stopLossStartPrice} / Adjusted start price: ${stopLossStartPrice}`);
571
571
 
572
- // 安全检查:确保价格不会超过最大值 / Safety check: ensure price doesn't exceed maximum
572
+ // Safety check: ensure the price does not exceed the maximum
573
573
  if (stopLossStartPrice >= CurveAMM.MAX_U128_PRICE) {
574
574
  throw new Error(`Stop loss price exceeded maximum after adjustment: ${stopLossStartPrice} >= ${CurveAMM.MAX_U128_PRICE}`);
575
575
  }
@@ -579,34 +579,34 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
579
579
  throw new Error('达到最大迭代次数,无法找到合适的止损价格 / Reached maximum iterations, cannot find suitable stop loss price');
580
580
  }
581
581
 
582
- // 计算最终返回值 / Calculate final return values
582
+ // Calculate final return values
583
583
  const executableStopLossPrice = stopLossStartPrice;
584
-
585
- // 计算止损百分比 / Calculate stop loss percentage
584
+
585
+ // Calculate stop loss percentage
586
586
  // For short position, stop loss price is higher than current price, so it's a positive percentage
587
587
  const stopLossPercentage = Number((BigInt(10000) * (executableStopLossPrice - currentPrice)) / currentPrice) / 100;
588
-
589
- // 计算杠杆比例 / Calculate leverage ratio
588
+
589
+ // Calculate leverage ratio
590
590
  // For short position, leverage = current price / (stop loss price - current price)
591
591
  const leverage = Number((BigInt(10000) * currentPrice) / (executableStopLossPrice - currentPrice)) / 10000;
592
592
 
593
- // 计算保证金 / Calculate margin requirement
594
- // 与合约公式一致 (long_short.rs 第890-894行):
593
+ // Calculate margin requirement
594
+ // Consistent with the contract formula (long_short.rs lines 890-894):
595
595
  // real_margin_sol = close_buy_sol_with_fee - output_sol - fee_sol
596
- // 其中 output_sol 是扣费后净SOL, fee_sol 是开仓手续费
597
- // 展开: real_margin_sol = close_buy_sol_with_fee - raw_sell_sol
596
+ // where output_sol is the net SOL after fees, and fee_sol is the open fee
597
+ // expanded: real_margin_sol = close_buy_sol_with_fee - raw_sell_sol
598
598
  let estimatedMargin = 0n;
599
- let rawSellSol = 0n; // 卖出 token 获得的原始 SOL(未扣费),供调用方计算 minSolOutput
599
+ let rawSellSol = 0n; // Raw SOL obtained from selling tokens (before fees), for the caller to compute minSolOutput
600
600
  try {
601
- // 1. 计算从当前价格卖出代币获得的原始SOL(未扣费)
601
+ // 1. Calculate the raw SOL (before fees) obtained from selling tokens at the current price
602
602
  const sellResult = CurveAMM.sellFromPriceWithTokenInputWithParams(currentPrice, sellTokenAmount, initialVirtualSol, initialVirtualToken);
603
603
  if (sellResult) {
604
- rawSellSol = sellResult[1]; // 卖出获得的原始SOL(未扣费)
604
+ rawSellSol = sellResult[1]; // Raw SOL obtained from the sale (before fees)
605
605
 
606
- // 2. 计算平仓成本(含手续费,使用 ceiling 除法与合约一致)
606
+ // 2. Calculate the close cost (including fees, using ceiling division to match the contract)
607
607
  const closeCostWithFee = CurveAMM.calculateTotalAmountWithFee(finalTradeAmount, borrowFee);
608
608
 
609
- // 3. 保证金 = 平仓成本(含费) - 原始卖出SOL
609
+ // 3. Margin = close cost (including fee) - raw sell SOL
610
610
  if (closeCostWithFee !== null && closeCostWithFee > rawSellSol) {
611
611
  estimatedMargin = closeCostWithFee - rawSellSol;
612
612
  }
@@ -625,7 +625,7 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
625
625
 
626
626
  return {
627
627
  executableStopLossPrice: executableStopLossPrice, // Calculated reasonable stop loss value
628
- tradeAmount: finalTradeAmount, // SOL input amount (平仓时买回 token 需要的 SOL)
628
+ tradeAmount: finalTradeAmount, // SOL input amount (SOL needed to buy back tokens at close)
629
629
  stopLossPercentage: stopLossPercentage, // Stop loss percentage relative to current price
630
630
  leverage: leverage, // Leverage ratio
631
631
  currentPrice: currentPrice, // Current price
@@ -633,7 +633,7 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
633
633
  originalStopLossPrice: BigInt(stopLossPrice), // Original stop loss price
634
634
  close_insert_indices: finalOverlapResult.close_insert_indices, // Candidate insertion indices for closing order
635
635
  estimatedMargin: estimatedMargin, // Estimated margin requirement in SOL (lamports)
636
- rawSellSol: rawSellSol // 卖出 token 获得的原始 SOL(未扣费),用于调用方计算 minSolOutput
636
+ rawSellSol: rawSellSol // Raw SOL obtained from selling tokens (before fees), used by the caller to compute minSolOutput
637
637
  };
638
638
 
639
639
  } catch (error) {
@@ -653,54 +653,54 @@ async function simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastP
653
653
  /**
654
654
  * Simulate long position stop loss calculation with SOL amount input
655
655
  *
656
- * 基于 SOL 金额的做多止损计算。该函数会自动计算出对应的代币数量,
657
- * 使得保证金需求接近用户输入的 SOL 金额。
656
+ * SOL-amount-based stop loss calculation for a long position. This function automatically computes the corresponding token amount,
657
+ * so that the margin requirement is close to the SOL amount provided by the user.
658
658
  *
659
- * @param {string} mint - Token address / 代币地址
660
- * @param {bigint|string|number} buySolAmount - SOL amount to spend for long position (u64 format, lamports) / 做多投入的SOL金额 (u64格式, lamports)
661
- * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format) / 用户期望的止损价格 (u128格式)
662
- * @param {Object|null} lastPrice - Token info, default null / 代币当前价格信息,默认null会自动获取
663
- * @param {Object|null} ordersData - Orders data, default null / 订单数据,默认null会自动获取
664
- * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%) / 借贷手续费率,默认2000 (2000/100000 = 0.02%)
659
+ * @param {string} mint - Token address
660
+ * @param {bigint|string|number} buySolAmount - SOL amount to spend for long position (u64 format, lamports)
661
+ * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format)
662
+ * @param {Object|null} lastPrice - Token info, default null (auto-fetched if null)
663
+ * @param {Object|null} ordersData - Orders data, default null (auto-fetched if null)
664
+ * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
665
665
  *
666
- * @returns {Promise<Object>} Stop loss analysis result / 止损分析结果对象
667
- * @returns {bigint} returns.executableStopLossPrice - 可执行止损价格 (u128格式) - 同 {@link simulateLongStopLoss}
668
- * @returns {bigint} returns.tradeAmount - 止损时预计卖出获得的SOL数量 (lamports) - 同 {@link simulateLongStopLoss}
669
- * @returns {number} returns.stopLossPercentage - 止损百分比 - 同 {@link simulateLongStopLoss}
670
- * @returns {number} returns.leverage - 杠杆倍数 - 同 {@link simulateLongStopLoss}
671
- * @returns {bigint} returns.currentPrice - 当前价格 (u128格式) - 同 {@link simulateLongStopLoss}
672
- * @returns {number} returns.iterations - 价格调整迭代次数 - 同 {@link simulateLongStopLoss}
673
- * @returns {bigint} returns.originalStopLossPrice - 原始止损价格 (u128格式) - 同 {@link simulateLongStopLoss}
674
- * @returns {number[]} returns.close_insert_indices - 平仓订单插入位置的候选索引数组 ⭐ - 同 {@link simulateLongStopLoss}
675
- * @returns {bigint} returns.estimatedMargin - 预估所需保证金 (SOL lamports) - 同 {@link simulateLongStopLoss}
676
- * @returns {bigint} returns.buyTokenAmount - 计算出的买入代币数量 ⭐ 额外字段
677
- * - 这是根据 buySolAmount 反向计算出的代币数量
678
- * - 使得 estimatedMargin 接近 buySolAmount
679
- * - 可以直接用于 sdk.trading.long() 的 buyTokenAmount 参数
680
- * @returns {number} returns.adjustmentIterations - 代币数量调整迭代次数 ⭐ 额外字段
681
- * - 二分查找算法调整代币数量的迭代次数
682
- * - 用于评估计算精度
666
+ * @returns {Promise<Object>} Stop loss analysis result
667
+ * @returns {bigint} returns.executableStopLossPrice - Executable stop loss price (u128 format) - same as {@link simulateLongStopLoss}
668
+ * @returns {bigint} returns.tradeAmount - Estimated SOL amount obtained from selling at stop loss (lamports) - same as {@link simulateLongStopLoss}
669
+ * @returns {number} returns.stopLossPercentage - Stop loss percentage - same as {@link simulateLongStopLoss}
670
+ * @returns {number} returns.leverage - Leverage ratio - same as {@link simulateLongStopLoss}
671
+ * @returns {bigint} returns.currentPrice - Current price (u128 format) - same as {@link simulateLongStopLoss}
672
+ * @returns {number} returns.iterations - Number of price adjustment iterations - same as {@link simulateLongStopLoss}
673
+ * @returns {bigint} returns.originalStopLossPrice - Original stop loss price (u128 format) - same as {@link simulateLongStopLoss}
674
+ * @returns {number[]} returns.close_insert_indices - Candidate index array for the closing order insertion position ⭐ - same as {@link simulateLongStopLoss}
675
+ * @returns {bigint} returns.estimatedMargin - Estimated required margin (SOL lamports) - same as {@link simulateLongStopLoss}
676
+ * @returns {bigint} returns.buyTokenAmount - Calculated token amount to buy ⭐ Additional field
677
+ * - This is the token amount reverse-calculated from buySolAmount
678
+ * - Such that estimatedMargin is close to buySolAmount
679
+ * - Can be used directly as the buyTokenAmount parameter of sdk.trading.long()
680
+ * @returns {number} returns.adjustmentIterations - Number of token amount adjustment iterations ⭐ Additional field
681
+ * - The number of iterations the binary search algorithm used to adjust the token amount
682
+ * - Used to assess calculation precision
683
683
  *
684
- * @throws {Error} 当缺少必需参数时
685
- * @throws {Error} 当无法获取价格或订单数据时
686
- * @throws {Error} 当无法计算代币数量时
684
+ * @throws {Error} When required parameters are missing
685
+ * @throws {Error} When price or orders data cannot be fetched
686
+ * @throws {Error} When the token amount cannot be calculated
687
687
  *
688
688
  * @example
689
- * // 基础用法: 投入 0.1 SOL 做多,止损价格为当前价格的97%
689
+ * // Basic usage: spend 0.1 SOL to go long, stop loss price at 97% of the current price
690
690
  * const result = await sdk.simulator.simulateLongSolStopLoss(
691
691
  * '4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X', // mint
692
- * 100000000n, // 0.1 SOL (精度10^9)
693
- * BigInt('97000000000000000000') // 止损价格
692
+ * 100000000n, // 0.1 SOL (precision 10^9)
693
+ * BigInt('97000000000000000000') // stop loss price
694
694
  * );
695
695
  *
696
- * console.log(`买入代币数量: ${result.buyTokenAmount}`);
697
- * console.log(`预估保证金: ${result.estimatedMargin} lamports`);
698
- * console.log(`插入位置索引: ${result.close_insert_indices}`);
696
+ * console.log(`Token amount to buy: ${result.buyTokenAmount}`);
697
+ * console.log(`Estimated margin: ${result.estimatedMargin} lamports`);
698
+ * console.log(`Insert position indices: ${result.close_insert_indices}`);
699
699
  *
700
- * @see {@link simulateLongStopLoss} 基于代币数量的做多止损计算
701
- * @see {@link simulateShortSolStopLoss} 基于SOL金额的做空止损计算
700
+ * @see {@link simulateLongStopLoss} Token-amount-based stop loss calculation for long positions
701
+ * @see {@link simulateShortSolStopLoss} SOL-amount-based stop loss calculation for short positions
702
702
  * @since 2.0.0
703
- * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
703
+ * @version 2.0.0 - Changed from returning prev_order_pda/next_order_pda to returning close_insert_indices
704
704
  */
705
705
  async function simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null, curveAccount = null) {
706
706
  try {
@@ -709,7 +709,7 @@ async function simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPr
709
709
  throw new Error('Missing required parameters');
710
710
  }
711
711
 
712
- // 如果没有传入 borrowFee 或池子参数,从链上一次性获取(支持外部传入 curveAccount 避免重复 RPC)
712
+ // If borrowFee or pool parameters are not provided, fetch them from the chain in a single call (supports passing in curveAccount externally to avoid duplicate RPC)
713
713
  if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
714
714
  if (!curveAccount) {
715
715
  curveAccount = await this.sdk.chain.getCurveAccount(mint, { skipBalances: true });
@@ -750,70 +750,70 @@ async function simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPr
750
750
  let iterations = 0;
751
751
  const maxIterations = 50;
752
752
 
753
- // 根据杠杆倍数动态计算二分查找上界
754
- // 高杠杆(如20x)时止损距离小,每个代币的保证金贡献小,需要更多代币才能消耗完保证金
753
+ // Dynamically compute the binary search upper bound based on the leverage ratio
754
+ // At high leverage (e.g. 20x) the stop loss distance is small, each token contributes little margin, so more tokens are needed to consume the full margin
755
755
  // Calculate dynamic binary search upper bound based on leverage
756
756
  const stopLossPriceBigInt = BigInt(stopLossPrice);
757
757
  const priceDiff = currentPrice - stopLossPriceBigInt;
758
758
  const estimatedLeverage = priceDiff > 0n ? Number(currentPrice * 10000n / priceDiff) / 10000 : 10;
759
- const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3倍安全系数
760
- const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // 最小10倍
759
+ const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3x safety factor
760
+ const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // minimum 10x
761
761
 
762
- // 使用二分查找算法找到 estimatedMargin < buySolAmount 的最大值
762
+ // Use a binary search algorithm to find the maximum estimatedMargin that is less than buySolAmount
763
763
  // Use binary search algorithm to find maximum estimatedMargin that is less than buySolAmount
764
- let left = 1n; // 最小值,确保有一个有效的下界
765
- let right = buyTokenAmount * multiplier; // 上界:根据杠杆动态计算
764
+ let left = 1n; // minimum value, ensuring a valid lower bound
765
+ let right = buyTokenAmount * multiplier; // upper bound: dynamically computed based on leverage
766
766
  let bestResult = null;
767
- let bestMargin = 0n; // 记录最大的合法 estimatedMargin
767
+ let bestMargin = 0n; // record the maximum valid estimatedMargin
768
768
  let bestTokenAmount = buyTokenAmount;
769
-
770
- // 二分查找主循环:寻找 estimatedMargin < buySolAmount 的最大值
769
+
770
+ // Binary search main loop: find the maximum estimatedMargin that is less than buySolAmount
771
771
  while (iterations < maxIterations && left <= right) {
772
772
  const mid = (left + right) / 2n;
773
-
774
- // 计算当前 token 数量的结果
773
+
774
+ // Calculate the result for the current token amount
775
775
  const currentResult = await simulateLongStopLoss.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
776
776
  const currentMargin = currentResult.estimatedMargin;
777
-
777
+
778
778
  //console.log(`Binary search iteration ${iterations}: tokenAmount=${mid}, estimatedMargin=${currentMargin}, target=${buySolAmount}`);
779
-
780
- // 只考虑 estimatedMargin < buySolAmount 的情况
779
+
780
+ // Only consider the case where estimatedMargin < buySolAmount
781
781
  if (currentMargin < BigInt(buySolAmount)) {
782
- // 这是一个合法的解,检查是否比当前最佳解更好
782
+ // This is a valid solution, check whether it is better than the current best solution
783
783
  if (currentMargin > bestMargin) {
784
784
  bestMargin = currentMargin;
785
785
  bestResult = currentResult;
786
786
  bestTokenAmount = mid;
787
787
  //console.log(`Found better solution: estimatedMargin=${currentMargin}, tokenAmount=${mid}`);
788
788
  }
789
-
790
- // 如果差距已经很小(距离目标值小于10000000 lamports),可以提前退出
789
+
790
+ // If the gap is already very small (within 10000000 lamports of the target), we can exit early
791
791
  if (BigInt(buySolAmount) - currentMargin <= 10000000n) {
792
792
  //console.log(`Found optimal solution: estimatedMargin=${currentMargin}, diff=${BigInt(buySolAmount) - currentMargin} (< 10000000 lamports tolerance)`);
793
793
  break;
794
794
  }
795
-
796
- // 继续向右搜索,寻找更大的合法值
795
+
796
+ // Continue searching to the right for a larger valid value
797
797
  left = mid + 1n;
798
798
  } else {
799
- // estimatedMargin >= buySolAmount,需要减少 tokenAmount
799
+ // estimatedMargin >= buySolAmount, need to reduce tokenAmount
800
800
  //console.log(`estimatedMargin too large (${currentMargin} >= ${buySolAmount}), searching left`);
801
801
  right = mid - 1n;
802
802
  }
803
-
803
+
804
804
  iterations++;
805
805
  }
806
-
807
- // 确保找到的结果满足要求
806
+
807
+ // Ensure the found result meets the requirement
808
808
  if (bestResult && bestMargin < BigInt(buySolAmount)) {
809
809
  stopLossResult = bestResult;
810
810
  buyTokenAmount = bestTokenAmount;
811
811
  //console.log(`Binary search completed: best tokenAmount=${bestTokenAmount}, estimatedMargin=${bestMargin}, target=${buySolAmount}`);
812
812
  } else {
813
- // 如果没有找到合法解,使用一个很小的 tokenAmount 作为安全回退
813
+ // If no valid solution is found, use a very small tokenAmount as a safe fallback
814
814
  //console.log(`No valid solution found (estimatedMargin < buySolAmount), using minimal tokenAmount`);
815
- buyTokenAmount = buyTokenAmount / 10n; // 使用更小的值
816
- if (buyTokenAmount <= 0n) buyTokenAmount = 1000000000n; // 最小值保护 (0.001 token with 9 decimals)
815
+ buyTokenAmount = buyTokenAmount / 10n; // use a smaller value
816
+ if (buyTokenAmount <= 0n) buyTokenAmount = 1000000000n; // minimum value protection (0.001 token with 9 decimals)
817
817
  stopLossResult = await simulateLongStopLoss.call(this, mint, buyTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
818
818
  }
819
819
 
@@ -837,54 +837,54 @@ async function simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPr
837
837
  /**
838
838
  * Simulate short position stop loss calculation with SOL amount input
839
839
  *
840
- * 基于 SOL 金额的做空止损计算。该函数会自动计算出对应的代币数量,
841
- * 使得保证金需求接近用户输入的 SOL 金额。
840
+ * SOL-amount-based stop loss calculation for a short position. This function automatically computes the corresponding token amount,
841
+ * so that the margin requirement is close to the SOL amount provided by the user.
842
842
  *
843
- * @param {string} mint - Token address / 代币地址
844
- * @param {bigint|string|number} sellSolAmount - SOL amount needed for short position stop loss (u64 format, lamports) / 做空投入的SOL金额 (u64格式, lamports)
845
- * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format) / 用户期望的止损价格 (u128格式)
846
- * @param {Object|null} lastPrice - Token info, default null / 代币当前价格信息,默认null会自动获取
847
- * @param {Object|null} ordersData - Orders data, default null / 订单数据,默认null会自动获取
848
- * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%) / 借贷手续费率,默认2000 (2000/100000 = 0.02%)
843
+ * @param {string} mint - Token address
844
+ * @param {bigint|string|number} sellSolAmount - SOL amount needed for short position stop loss (u64 format, lamports)
845
+ * @param {bigint|string|number} stopLossPrice - User desired stop loss price (u128 format)
846
+ * @param {Object|null} lastPrice - Token info, default null (auto-fetched if null)
847
+ * @param {Object|null} ordersData - Orders data, default null (auto-fetched if null)
848
+ * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
849
849
  *
850
- * @returns {Promise<Object>} Stop loss analysis result / 止损分析结果对象
851
- * @returns {bigint} returns.executableStopLossPrice - 可执行止损价格 (u128格式) - 同 {@link simulateShortStopLoss}
852
- * @returns {bigint} returns.tradeAmount - 止损时预计买入需要的SOL数量 (lamports) - 同 {@link simulateShortStopLoss}
853
- * @returns {number} returns.stopLossPercentage - 止损百分比 - 同 {@link simulateShortStopLoss}
854
- * @returns {number} returns.leverage - 杠杆倍数 - 同 {@link simulateShortStopLoss}
855
- * @returns {bigint} returns.currentPrice - 当前价格 (u128格式) - 同 {@link simulateShortStopLoss}
856
- * @returns {number} returns.iterations - 价格调整迭代次数 - 同 {@link simulateShortStopLoss}
857
- * @returns {bigint} returns.originalStopLossPrice - 原始止损价格 (u128格式) - 同 {@link simulateShortStopLoss}
858
- * @returns {number[]} returns.close_insert_indices - 平仓订单插入位置的候选索引数组 ⭐ - 同 {@link simulateShortStopLoss}
859
- * @returns {bigint} returns.estimatedMargin - 预估所需保证金 (SOL lamports) - 同 {@link simulateShortStopLoss}
860
- * @returns {bigint} returns.sellTokenAmount - 计算出的卖出代币数量 ⭐ 额外字段
861
- * - 这是根据 sellSolAmount 反向计算出的代币数量
862
- * - 使得 estimatedMargin 接近 sellSolAmount
863
- * - 可以直接用于 sdk.trading.short() 的 borrowSellTokenAmount 参数
864
- * @returns {number} returns.adjustmentIterations - 代币数量调整迭代次数 ⭐ 额外字段
865
- * - 二分查找算法调整代币数量的迭代次数
866
- * - 用于评估计算精度
850
+ * @returns {Promise<Object>} Stop loss analysis result
851
+ * @returns {bigint} returns.executableStopLossPrice - Executable stop loss price (u128 format) - same as {@link simulateShortStopLoss}
852
+ * @returns {bigint} returns.tradeAmount - Estimated SOL amount needed to buy at stop loss (lamports) - same as {@link simulateShortStopLoss}
853
+ * @returns {number} returns.stopLossPercentage - Stop loss percentage - same as {@link simulateShortStopLoss}
854
+ * @returns {number} returns.leverage - Leverage ratio - same as {@link simulateShortStopLoss}
855
+ * @returns {bigint} returns.currentPrice - Current price (u128 format) - same as {@link simulateShortStopLoss}
856
+ * @returns {number} returns.iterations - Number of price adjustment iterations - same as {@link simulateShortStopLoss}
857
+ * @returns {bigint} returns.originalStopLossPrice - Original stop loss price (u128 format) - same as {@link simulateShortStopLoss}
858
+ * @returns {number[]} returns.close_insert_indices - Candidate index array for the closing order insertion position ⭐ - same as {@link simulateShortStopLoss}
859
+ * @returns {bigint} returns.estimatedMargin - Estimated required margin (SOL lamports) - same as {@link simulateShortStopLoss}
860
+ * @returns {bigint} returns.sellTokenAmount - Calculated token amount to sell ⭐ Additional field
861
+ * - This is the token amount reverse-calculated from sellSolAmount
862
+ * - Such that estimatedMargin is close to sellSolAmount
863
+ * - Can be used directly as the borrowSellTokenAmount parameter of sdk.trading.short()
864
+ * @returns {number} returns.adjustmentIterations - Number of token amount adjustment iterations ⭐ Additional field
865
+ * - The number of iterations the binary search algorithm used to adjust the token amount
866
+ * - Used to assess calculation precision
867
867
  *
868
- * @throws {Error} 当缺少必需参数时
869
- * @throws {Error} 当无法获取价格或订单数据时
870
- * @throws {Error} 当无法计算代币数量时
868
+ * @throws {Error} When required parameters are missing
869
+ * @throws {Error} When price or orders data cannot be fetched
870
+ * @throws {Error} When the token amount cannot be calculated
871
871
  *
872
872
  * @example
873
- * // 基础用法: 投入 0.1 SOL 做空,止损价格为当前价格的103%
873
+ * // Basic usage: spend 0.1 SOL to go short, stop loss price at 103% of the current price
874
874
  * const result = await sdk.simulator.simulateShortSolStopLoss(
875
875
  * '4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X', // mint
876
- * 100000000n, // 0.1 SOL (精度10^9)
877
- * BigInt('103000000000000000000') // 止损价格
876
+ * 100000000n, // 0.1 SOL (precision 10^9)
877
+ * BigInt('103000000000000000000') // stop loss price
878
878
  * );
879
879
  *
880
- * console.log(`卖出代币数量: ${result.sellTokenAmount}`);
881
- * console.log(`预估保证金: ${result.estimatedMargin} lamports`);
882
- * console.log(`插入位置索引: ${result.close_insert_indices}`);
880
+ * console.log(`Token amount to sell: ${result.sellTokenAmount}`);
881
+ * console.log(`Estimated margin: ${result.estimatedMargin} lamports`);
882
+ * console.log(`Insert position indices: ${result.close_insert_indices}`);
883
883
  *
884
- * @see {@link simulateShortStopLoss} 基于代币数量的做空止损计算
885
- * @see {@link simulateLongSolStopLoss} 基于SOL金额的做多止损计算
884
+ * @see {@link simulateShortStopLoss} Token-amount-based stop loss calculation for short positions
885
+ * @see {@link simulateLongSolStopLoss} SOL-amount-based stop loss calculation for long positions
886
886
  * @since 2.0.0
887
- * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
887
+ * @version 2.0.0 - Changed from returning prev_order_pda/next_order_pda to returning close_insert_indices
888
888
  */
889
889
  async function simulateShortSolStopLoss(mint, sellSolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null, curveAccount = null) {
890
890
  try {
@@ -893,7 +893,7 @@ async function simulateShortSolStopLoss(mint, sellSolAmount, stopLossPrice, last
893
893
  throw new Error('Missing required parameters');
894
894
  }
895
895
 
896
- // 如果没有传入 borrowFee 或池子参数,从链上一次性获取(支持外部传入 curveAccount 避免重复 RPC)
896
+ // If borrowFee or pool parameters are not provided, fetch them from the chain in a single call (supports passing in curveAccount externally to avoid duplicate RPC)
897
897
  if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
898
898
  if (!curveAccount) {
899
899
  curveAccount = await this.sdk.chain.getCurveAccount(mint, { skipBalances: true });
@@ -936,70 +936,70 @@ async function simulateShortSolStopLoss(mint, sellSolAmount, stopLossPrice, last
936
936
  let iterations = 0;
937
937
  const maxIterations = 50;
938
938
 
939
- // 根据杠杆倍数动态计算二分查找上界
940
- // 高杠杆(如20x)时止损距离小,每个代币的保证金贡献小,需要更多代币才能消耗完保证金
939
+ // Dynamically compute the binary search upper bound based on the leverage ratio
940
+ // At high leverage (e.g. 20x) the stop loss distance is small, each token contributes little margin, so more tokens are needed to consume the full margin
941
941
  // Calculate dynamic binary search upper bound based on leverage
942
942
  const stopLossPriceBigInt = BigInt(stopLossPrice);
943
943
  const priceDiff = stopLossPriceBigInt - currentPrice;
944
944
  const estimatedLeverage = priceDiff > 0n ? Number(currentPrice * 10000n / priceDiff) / 10000 : 10;
945
- const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3倍安全系数
946
- const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // 最小10倍
945
+ const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3x safety factor
946
+ const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // minimum 10x
947
947
 
948
- // 使用二分查找算法找到 estimatedMargin < sellSolAmount 的最大值
948
+ // Use a binary search algorithm to find the maximum estimatedMargin that is less than sellSolAmount
949
949
  // Use binary search algorithm to find maximum estimatedMargin that is less than sellSolAmount
950
- let left = 1n; // 最小值,确保有一个有效的下界
951
- let right = sellTokenAmount * multiplier; // 上界:根据杠杆动态计算
950
+ let left = 1n; // minimum value, ensuring a valid lower bound
951
+ let right = sellTokenAmount * multiplier; // upper bound: dynamically computed based on leverage
952
952
  let bestResult = null;
953
- let bestMargin = 0n; // 记录最大的合法 estimatedMargin
953
+ let bestMargin = 0n; // record the maximum valid estimatedMargin
954
954
  let bestTokenAmount = sellTokenAmount;
955
-
956
- // 二分查找主循环:寻找 estimatedMargin < sellSolAmount 的最大值
955
+
956
+ // Binary search main loop: find the maximum estimatedMargin that is less than sellSolAmount
957
957
  while (iterations < maxIterations && left <= right) {
958
958
  const mid = (left + right) / 2n;
959
-
960
- // 计算当前 token 数量的结果
959
+
960
+ // Calculate the result for the current token amount
961
961
  const currentResult = await simulateShortStopLoss.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
962
962
  const currentMargin = currentResult.estimatedMargin;
963
-
963
+
964
964
  //console.log(`Binary search iteration ${iterations}: tokenAmount=${mid}, estimatedMargin=${currentMargin}, target=${sellSolAmount}`);
965
-
966
- // 只考虑 estimatedMargin < sellSolAmount 的情况
965
+
966
+ // Only consider the case where estimatedMargin < sellSolAmount
967
967
  if (currentMargin < BigInt(sellSolAmount)) {
968
- // 这是一个合法的解,检查是否比当前最佳解更好
968
+ // This is a valid solution, check whether it is better than the current best solution
969
969
  if (currentMargin > bestMargin) {
970
970
  bestMargin = currentMargin;
971
971
  bestResult = currentResult;
972
972
  bestTokenAmount = mid;
973
973
  //console.log(`Found better solution: estimatedMargin=${currentMargin}, tokenAmount=${mid}`);
974
974
  }
975
-
976
- // 如果差距已经很小(距离目标值小于10000000 lamports),可以提前退出
975
+
976
+ // If the gap is already very small (within 10000000 lamports of the target), we can exit early
977
977
  if (BigInt(sellSolAmount) - currentMargin <= 10000000n) {
978
978
  //console.log(`Found optimal solution: estimatedMargin=${currentMargin}, diff=${BigInt(sellSolAmount) - currentMargin} (< 10000000 lamports tolerance)`);
979
979
  break;
980
980
  }
981
-
982
- // 继续向右搜索,寻找更大的合法值
981
+
982
+ // Continue searching to the right for a larger valid value
983
983
  left = mid + 1n;
984
984
  } else {
985
- // estimatedMargin >= sellSolAmount,需要减少 tokenAmount
985
+ // estimatedMargin >= sellSolAmount, need to reduce tokenAmount
986
986
  //console.log(`estimatedMargin too large (${currentMargin} >= ${sellSolAmount}), searching left`);
987
987
  right = mid - 1n;
988
988
  }
989
-
989
+
990
990
  iterations++;
991
991
  }
992
-
993
- // 确保找到的结果满足要求
992
+
993
+ // Ensure the found result meets the requirement
994
994
  if (bestResult && bestMargin < BigInt(sellSolAmount)) {
995
995
  stopLossResult = bestResult;
996
996
  sellTokenAmount = bestTokenAmount;
997
997
  //console.log(`Binary search completed: best tokenAmount=${bestTokenAmount}, estimatedMargin=${bestMargin}, target=${sellSolAmount}`);
998
998
  } else {
999
- // 如果没有找到合法解,使用一个很小的 tokenAmount 作为安全回退
999
+ // If no valid solution is found, use a very small tokenAmount as a safe fallback
1000
1000
  //console.log(`No valid solution found (estimatedMargin < sellSolAmount), using minimal tokenAmount`);
1001
- sellTokenAmount = sellTokenAmount / 10n; // 使用更小的值
1002
- if (sellTokenAmount <= 0n) sellTokenAmount = 1000000000n; // 最小值保护 (0.001 token with 9 decimals)
1001
+ sellTokenAmount = sellTokenAmount / 10n; // use a smaller value
1002
+ if (sellTokenAmount <= 0n) sellTokenAmount = 1000000000n; // minimum value protection (0.001 token with 9 decimals)
1003
1003
  stopLossResult = await simulateShortStopLoss.call(this, mint, sellTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
1004
1004
  }
1005
1005