100x-sdk 1.0.2 → 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.
- package/dist/100x-sdk.cjs.js +7037 -3901
- package/dist/100x-sdk.esm.js +6240 -3341
- package/dist/100x-sdk.js +6240 -3341
- package/dist/100x-sdk.js.map +1 -1
- package/dist/index.d.ts +19 -19
- package/package.json +1 -1
- package/src/modules/chain.js +26 -26
- package/src/modules/fast.js +88 -88
- package/src/modules/param.js +6 -6
- package/src/modules/simulator/buy_sell_token.js +38 -39
- package/src/modules/simulator/calcLiq.js +176 -198
- package/src/modules/simulator/calc_sol_liq.js +40 -40
- package/src/modules/simulator/close_indices.js +51 -54
- package/src/modules/simulator/long_shrot_stop.js +332 -332
- package/src/modules/simulator/stop_loss_utils.js +125 -125
- package/src/modules/simulator/utils.js +1 -2
- package/src/modules/simulator.js +14 -19
- package/src/modules/token.js +69 -69
- package/src/modules/tools.js +1 -1
- package/src/modules/trading.js +97 -97
- package/src/sdk.js +22 -23
- package/src/types/index.d.ts +19 -19
- package/src/utils/constants.js +2 -2
- package/src/utils/curve_amm.js +54 -54
- package/src/utils/orderUtils.js +1 -3
|
@@ -4,74 +4,63 @@ const Decimal = require('decimal.js');
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* 此函数分析买入操作对价格区间内流动性的影响,计算可用的自由流动性、锁定流动性,
|
|
10
|
-
* 并支持跳过指定订单(将其流动性视为可用)。适用于做多订单(up_orders)场景。
|
|
7
|
+
* Calculate liquidity impact for token buy operations
|
|
8
|
+
*
|
|
11
9
|
* This function analyzes the liquidity impact of buy operations within price ranges,
|
|
12
10
|
* calculates available free liquidity, locked liquidity, and supports skipping specific
|
|
13
11
|
* orders (treating their liquidity as available). Applicable for long orders (up_orders) scenarios.
|
|
14
|
-
*
|
|
15
|
-
* @param {bigint|string|number} price -
|
|
16
|
-
* @param {bigint|string|number} buyTokenAmount -
|
|
17
|
-
* @param {Array<Object>} orders -
|
|
18
|
-
* - order_type: {number}
|
|
19
|
-
* - mint: {string}
|
|
20
|
-
* - user: {string}
|
|
21
|
-
* - lock_lp_start_price: {string} LP
|
|
22
|
-
* - lock_lp_end_price: {string} LP
|
|
23
|
-
* - lock_lp_sol_amount: {number}
|
|
24
|
-
* - lock_lp_token_amount: {number}
|
|
25
|
-
* - start_time: {number}
|
|
26
|
-
* - end_time: {number}
|
|
27
|
-
* - margin_sol_amount: {number}
|
|
28
|
-
* - borrow_amount: {number}
|
|
29
|
-
* - position_asset_amount: {number}
|
|
30
|
-
* - borrow_fee: {number}
|
|
31
|
-
* - order_pda: {string}
|
|
32
|
-
* @param {number} onceMaxOrder -
|
|
33
|
-
* @param {string|null} passOrder -
|
|
34
|
-
*
|
|
35
|
-
* @returns {Object}
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* - free_lp_sol_amount_sum: {bigint}
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* -
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* -
|
|
51
|
-
*
|
|
52
|
-
* -
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* - real_lp_sol_amount: {bigint} 实际SOL使用量,考虑真实流动性分布的精确SOL需求。0表示当前自由流动性不足以满足买入需求,需要强平更多订单
|
|
61
|
-
* Actual SOL usage, precise SOL requirement considering real liquidity distribution. 0 means current free liquidity insufficient for buy requirement, need to force close more orders
|
|
62
|
-
*
|
|
63
|
-
* @throws {Error} 参数验证错误:price、buyTokenAmount、orders、onceMaxOrder 参数无效 Parameter validation error: invalid price, buyTokenAmount, orders, or onceMaxOrder
|
|
64
|
-
* @throws {Error} 价格转换错误:无法将价格参数转换为 BigInt Price conversion error: cannot convert price parameters to BigInt
|
|
65
|
-
* @throws {Error} 流动性计算错误:CurveAMM 计算失败或数值转换错误 Liquidity calculation error: CurveAMM calculation failure or value conversion error
|
|
66
|
-
* @throws {Error} 间隙流动性计算失败:价格间隙流动性计算异常 Gap liquidity calculation failure: price gap liquidity calculation exception
|
|
67
|
-
* @throws {Error} 无限流动性计算失败:最大价格流动性计算异常 Infinite liquidity calculation failure: max price liquidity calculation exception
|
|
68
|
-
* @throws {Error} 订单数据格式错误:订单对象缺少必需字段 Order data format error: order object missing required fields
|
|
12
|
+
*
|
|
13
|
+
* @param {bigint|string|number} price - Current token price, used as calculation start price
|
|
14
|
+
* @param {bigint|string|number} buyTokenAmount - Amount of tokens to buy, target purchase amount
|
|
15
|
+
* @param {Array<Object>} orders - Array of orders sorted by lock_lp_start_price (ascending):
|
|
16
|
+
* - order_type: {number} Order type (1=long, 2=short)
|
|
17
|
+
* - mint: {string} Token mint address
|
|
18
|
+
* - user: {string} User address
|
|
19
|
+
* - lock_lp_start_price: {string} LP lock start price (required)
|
|
20
|
+
* - lock_lp_end_price: {string} LP lock end price (required)
|
|
21
|
+
* - lock_lp_sol_amount: {number} Locked SOL amount (required)
|
|
22
|
+
* - lock_lp_token_amount: {number} Locked token amount (required)
|
|
23
|
+
* - start_time: {number} Start timestamp
|
|
24
|
+
* - end_time: {number} End timestamp
|
|
25
|
+
* - margin_sol_amount: {number} Margin SOL amount
|
|
26
|
+
* - borrow_amount: {number} Borrow amount
|
|
27
|
+
* - position_asset_amount: {number} Position asset amount
|
|
28
|
+
* - borrow_fee: {number} Borrow fee
|
|
29
|
+
* - order_pda: {string} Order PDA address (required for passOrder matching)
|
|
30
|
+
* @param {number} onceMaxOrder - Maximum orders to process at once, limits traversal range
|
|
31
|
+
* @param {string|null} passOrder - Order PDA address string to skip, when this value matches an order's order_pda, skip that order and count its liquidity as free liquidity
|
|
32
|
+
*
|
|
33
|
+
* @returns {Object} Liquidity calculation result object with detailed liquidity analysis data:
|
|
34
|
+
*
|
|
35
|
+
* **Free Liquidity:**
|
|
36
|
+
* - free_lp_sol_amount_sum: {bigint} Total available free liquidity SOL amount, includes: 1) price gap liquidity 2) skipped order liquidity 3) infinite liquidity (if any)
|
|
37
|
+
* - free_lp_token_amount_sum: {bigint} Total available free liquidity token amount, corresponds to SOL, represents max tokens buyable without force closing any orders
|
|
38
|
+
*
|
|
39
|
+
* **Locked Liquidity:**
|
|
40
|
+
* - lock_lp_sol_amount_sum: {bigint} Total locked liquidity SOL amount, excludes skipped orders, this liquidity is not directly usable
|
|
41
|
+
* - lock_lp_token_amount_sum: {bigint} Total locked liquidity token amount, excludes skipped orders, corresponds to locked SOL liquidity
|
|
42
|
+
*
|
|
43
|
+
* **Liquidity Status Indicators:**
|
|
44
|
+
* - has_infinite_lp: {boolean} Whether includes infinite liquidity, true means order chain ended and liquidity to max price (MAX_U128_PRICE) was calculated
|
|
45
|
+
* - pass_order_id: {number} Index of skipped order in array, -1 means no order skipped, >=0 means order at that index was skipped
|
|
46
|
+
*
|
|
47
|
+
* **Buy Execution Info:**
|
|
48
|
+
* - force_close_num: {number} Number of orders that need to be force closed, indicates how many orders need force closure to buy target amount, 0 means no force closure needed
|
|
49
|
+
* - ideal_lp_sol_amount: {bigint} Ideal SOL usage, theoretical minimum SOL requirement calculated directly from current price using CurveAMM, ignores liquidity distribution
|
|
50
|
+
* - real_lp_sol_amount: {bigint} Actual SOL usage, precise SOL requirement considering real liquidity distribution. 0 means current free liquidity insufficient for buy requirement, need to force close more orders
|
|
51
|
+
*
|
|
52
|
+
* @throws {Error} Parameter validation error: invalid price, buyTokenAmount, orders, or onceMaxOrder
|
|
53
|
+
* @throws {Error} Price conversion error: cannot convert price parameters to BigInt
|
|
54
|
+
* @throws {Error} Liquidity calculation error: CurveAMM calculation failure or value conversion error
|
|
55
|
+
* @throws {Error} Gap liquidity calculation failure: price gap liquidity calculation exception
|
|
56
|
+
* @throws {Error} Infinite liquidity calculation failure: max price liquidity calculation exception
|
|
57
|
+
* @throws {Error} Order data format error: order object missing required fields
|
|
69
58
|
*/
|
|
70
59
|
function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder = null, initialVirtualSol = null, initialVirtualToken = null) {
|
|
71
|
-
//
|
|
72
|
-
//
|
|
60
|
+
// Since this is a buy operation, the orders are definitely in the up_orders direction lock_lp_start_price < lock_lp_end_price
|
|
61
|
+
// And lock_lp_start_price is sorted in ascending order in orders
|
|
73
62
|
|
|
74
|
-
//
|
|
63
|
+
// Parameter validation
|
|
75
64
|
if (!price && price !== 0) {
|
|
76
65
|
throw new Error('参数验证错误:price 参数不能为空 Parameter validation error: price cannot be null');
|
|
77
66
|
}
|
|
@@ -89,15 +78,15 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
89
78
|
}
|
|
90
79
|
|
|
91
80
|
const result = {
|
|
92
|
-
free_lp_sol_amount_sum: 0n, //
|
|
93
|
-
free_lp_token_amount_sum: 0n, //
|
|
81
|
+
free_lp_sol_amount_sum: 0n, // Amount of SOL liquidity usable in the gaps
|
|
82
|
+
free_lp_token_amount_sum: 0n, // Amount of token liquidity usable in the gaps
|
|
94
83
|
lock_lp_sol_amount_sum: 0n,
|
|
95
84
|
lock_lp_token_amount_sum: 0n,
|
|
96
|
-
has_infinite_lp: false, //
|
|
97
|
-
pass_order_id: -1, //
|
|
98
|
-
force_close_num: 0, //
|
|
99
|
-
ideal_lp_sol_amount: 0n, //
|
|
100
|
-
real_lp_sol_amount: 0n, //
|
|
85
|
+
has_infinite_lp: false, // Whether includes infinite liquidity
|
|
86
|
+
pass_order_id: -1, // Index of skipped order
|
|
87
|
+
force_close_num: 0, // Number of force closed orders
|
|
88
|
+
ideal_lp_sol_amount: 0n, // Amount of SOL used to buy buyTokenAmount under ideal conditions
|
|
89
|
+
real_lp_sol_amount: 0n, // Amount of SOL actually used to buy buyTokenAmount
|
|
101
90
|
}
|
|
102
91
|
|
|
103
92
|
|
|
@@ -110,7 +99,7 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
110
99
|
throw new Error(`价格转换错误:无法将 buyTokenAmount 转换为 BigInt Price conversion error: Cannot convert buyTokenAmount to BigInt - ${error.message}`);
|
|
111
100
|
}
|
|
112
101
|
|
|
113
|
-
//
|
|
102
|
+
// Declare variable for tracking the previous free liquidity total
|
|
114
103
|
let prev_free_lp_sol_amount_sum;
|
|
115
104
|
|
|
116
105
|
//result.ideal_lp_token_amount_sum = buyTokenAmountBigInt;
|
|
@@ -126,13 +115,13 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
126
115
|
initialVirtualSolDecimal,
|
|
127
116
|
initialVirtualTokenDecimal
|
|
128
117
|
);
|
|
129
|
-
// console.log(
|
|
118
|
+
// console.log(`ideal calculation: current price=${priceBigInt}, target token=${buyTokenAmountBigInt}, ideal SOL=${result.ideal_lp_sol_amount}`);
|
|
130
119
|
} catch (error) {
|
|
131
120
|
throw new Error(`buy流动性计算错误:理想流动性计算失败 Liquidity calculation error: Ideal liquidity calculation failed - ${error.message}`);
|
|
132
121
|
}
|
|
133
122
|
|
|
134
123
|
|
|
135
|
-
// orders
|
|
124
|
+
// orders length of 0 requires separate calculation
|
|
136
125
|
if (orders.length === 0) {
|
|
137
126
|
|
|
138
127
|
|
|
@@ -154,14 +143,14 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
154
143
|
|
|
155
144
|
|
|
156
145
|
|
|
157
|
-
//
|
|
146
|
+
// Choose the smaller value for traversal
|
|
158
147
|
const loopCount = Math.min(orders.length, onceMaxOrder);
|
|
159
148
|
|
|
160
149
|
let counti = 0;
|
|
161
150
|
for (let i = 0; i < loopCount; i++) {
|
|
162
151
|
const order = orders[i];
|
|
163
152
|
|
|
164
|
-
//
|
|
153
|
+
// Validate order data format
|
|
165
154
|
if (!order) {
|
|
166
155
|
throw new Error(`订单数据格式错误:订单 ${i} 为空 Order data format error: Order ${i} is null`);
|
|
167
156
|
}
|
|
@@ -173,15 +162,15 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
173
162
|
}
|
|
174
163
|
|
|
175
164
|
|
|
176
|
-
//
|
|
165
|
+
// Calculate gap liquidity
|
|
177
166
|
let startPrice, endPrice;
|
|
178
167
|
try {
|
|
179
168
|
if (i === 0) {
|
|
180
|
-
//
|
|
169
|
+
// First order: use the gap from current price to order start price
|
|
181
170
|
startPrice = BigInt(price);
|
|
182
171
|
endPrice = BigInt(order.lock_lp_start_price);
|
|
183
172
|
} else {
|
|
184
|
-
//
|
|
173
|
+
// Subsequent orders: use the gap from previous order end price to current order start price
|
|
185
174
|
startPrice = BigInt(orders[i - 1].lock_lp_end_price);
|
|
186
175
|
endPrice = BigInt(order.lock_lp_start_price);
|
|
187
176
|
}
|
|
@@ -190,7 +179,7 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
190
179
|
}
|
|
191
180
|
|
|
192
181
|
|
|
193
|
-
//
|
|
182
|
+
// If a price gap exists, calculate free liquidity
|
|
194
183
|
if (endPrice > startPrice) {
|
|
195
184
|
try {
|
|
196
185
|
const initialVirtualSolDecimal = new Decimal(initialVirtualSol).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL);
|
|
@@ -205,30 +194,30 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
205
194
|
const [solAmount, tokenAmount] = gapLiquidity;
|
|
206
195
|
|
|
207
196
|
try {
|
|
208
|
-
prev_free_lp_sol_amount_sum = result.free_lp_sol_amount_sum; //
|
|
197
|
+
prev_free_lp_sol_amount_sum = result.free_lp_sol_amount_sum; // Previous value
|
|
209
198
|
result.free_lp_sol_amount_sum += BigInt(solAmount);
|
|
210
199
|
result.free_lp_token_amount_sum += BigInt(tokenAmount);
|
|
211
|
-
// console.log(
|
|
200
|
+
// console.log(`gap[${i}]: ${startPrice}→${endPrice}, gap SOL=${solAmount}, gap Token=${tokenAmount}, cumulative free Token=${result.free_lp_token_amount_sum}`);
|
|
212
201
|
} catch (error) {
|
|
213
202
|
throw new Error(`流动性计算错误:无法转换间隙流动性数值 Liquidity calculation error: Cannot convert gap liquidity values - ${error.message}`);
|
|
214
203
|
}
|
|
215
204
|
|
|
216
205
|
|
|
217
|
-
//
|
|
206
|
+
// Calculate the actual amount of SOL used, until enough can be bought
|
|
218
207
|
if (result.real_lp_sol_amount === 0n) {
|
|
219
208
|
if (result.free_lp_token_amount_sum > buyTokenAmountBigInt) {
|
|
220
|
-
//
|
|
221
|
-
//
|
|
209
|
+
// At this point the gap liquidity is already enough to buy
|
|
210
|
+
// Calculate the final precise amount of token to buy
|
|
222
211
|
try {
|
|
223
212
|
const actualBuyAmount = buyTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(tokenAmount));
|
|
224
213
|
// console.log("actualBuyAmount",actualBuyAmount)
|
|
225
214
|
const [, preciseSol] = CurveAMM.buyFromPriceWithTokenOutput(startPrice, actualBuyAmount)
|
|
226
215
|
result.real_lp_sol_amount = prev_free_lp_sol_amount_sum + BigInt(preciseSol);
|
|
227
216
|
|
|
228
|
-
// console.log(
|
|
229
|
-
result.force_close_num = counti; //
|
|
217
|
+
// console.log(`actual calculation[${i}]: free liquidity sufficient, actualBuyAmount=${actualBuyAmount}, preciseSol=${preciseSol}, actual SOL=${result.real_lp_sol_amount}`);
|
|
218
|
+
result.force_close_num = counti; // Number of force closed orders
|
|
230
219
|
} catch (error) {
|
|
231
|
-
// console.log('
|
|
220
|
+
// console.log('error details:', error);
|
|
232
221
|
throw new Error(`流动性计算错误:精确SOL计算失败 Liquidity calculation error: Precise SOL calculation failed - ${error.message}`);
|
|
233
222
|
}
|
|
234
223
|
}
|
|
@@ -246,13 +235,13 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
246
235
|
} else {
|
|
247
236
|
}
|
|
248
237
|
|
|
249
|
-
//
|
|
238
|
+
// Check whether this order needs to be skipped (passOrder logic)
|
|
250
239
|
//const shouldSkipOrder = passOrder && typeof passOrder === 'string' && order.order_pda === passOrder;
|
|
251
240
|
|
|
252
241
|
|
|
253
242
|
if (passOrder == order.order_pda) {
|
|
254
243
|
|
|
255
|
-
//
|
|
244
|
+
// Add the skipped order's liquidity to the free liquidity
|
|
256
245
|
try {
|
|
257
246
|
if (order.lock_lp_sol_amount === undefined || order.lock_lp_sol_amount === null) {
|
|
258
247
|
throw new Error(`订单数据格式错误:跳过订单 ${i} 缺少 lock_lp_sol_amount Order data format error: Skipped order ${i} missing lock_lp_sol_amount`);
|
|
@@ -261,25 +250,25 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
261
250
|
throw new Error(`订单数据格式错误:跳过订单 ${i} 缺少 lock_lp_token_amount Order data format error: Skipped order ${i} missing lock_lp_token_amount`);
|
|
262
251
|
}
|
|
263
252
|
|
|
264
|
-
const prevFreeSolSum = result.free_lp_sol_amount_sum; //
|
|
253
|
+
const prevFreeSolSum = result.free_lp_sol_amount_sum; // Save the previous value for calculation
|
|
265
254
|
result.free_lp_sol_amount_sum += BigInt(order.lock_lp_sol_amount);
|
|
266
255
|
result.free_lp_token_amount_sum += BigInt(order.lock_lp_token_amount);
|
|
267
256
|
|
|
268
257
|
result.pass_order_id = i;
|
|
269
258
|
|
|
270
259
|
|
|
271
|
-
//
|
|
260
|
+
// Check whether the free liquidity after skipping the order already meets the buy requirement
|
|
272
261
|
if (result.real_lp_sol_amount === 0n) {
|
|
273
262
|
if (result.free_lp_token_amount_sum >= buyTokenAmountBigInt) {
|
|
274
|
-
//
|
|
263
|
+
// Free liquidity is already enough for the buy requirement
|
|
275
264
|
try {
|
|
276
265
|
//const remainingToken = result.free_lp_token_amount_sum - buyTokenAmountBigInt;
|
|
277
|
-
//
|
|
266
|
+
// Calculate from the current price how much SOL is needed to buy the precise token amount
|
|
278
267
|
const targetPrice = i === 0 ? BigInt(price) : BigInt(orders[i - 1].lock_lp_end_price);
|
|
279
268
|
const actualBuyAmount = buyTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(order.lock_lp_token_amount));
|
|
280
269
|
const [, preciseSol] = CurveAMM.buyFromPriceWithTokenOutput(targetPrice, actualBuyAmount);
|
|
281
270
|
result.real_lp_sol_amount = prevFreeSolSum + BigInt(preciseSol);
|
|
282
|
-
// console.log(
|
|
271
|
+
// console.log(`actual calculation[${i}]: sufficient after skipping order, targetPrice=${targetPrice}, preciseSol=${preciseSol}, actual SOL=${result.real_lp_sol_amount}`);
|
|
283
272
|
result.force_close_num = counti;
|
|
284
273
|
} catch (error) {
|
|
285
274
|
throw new Error(`流动性计算错误:跳过订单后精确SOL计算失败 Liquidity calculation error: Precise SOL calculation failed after skipping order - ${error.message}`);
|
|
@@ -294,7 +283,7 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
294
283
|
throw new Error(`流动性计算错误:无法处理跳过订单 ${i} 的流动性 Liquidity calculation error: Cannot process skipped order ${i} liquidity - ${error.message}`);
|
|
295
284
|
}
|
|
296
285
|
} else {
|
|
297
|
-
//
|
|
286
|
+
// Accumulate locked liquidity (normal case)
|
|
298
287
|
try {
|
|
299
288
|
if (order.lock_lp_sol_amount === undefined || order.lock_lp_sol_amount === null) {
|
|
300
289
|
throw new Error(`订单数据格式错误:订单 ${i} 缺少 lock_lp_sol_amount Order data format error: Order ${i} missing lock_lp_sol_amount`);
|
|
@@ -320,7 +309,7 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
320
309
|
|
|
321
310
|
}
|
|
322
311
|
|
|
323
|
-
//
|
|
312
|
+
// If the number of traversed orders is less than or equal to onceMaxOrder, the chain has ended and infinite liquidity needs to be calculated
|
|
324
313
|
if (orders.length <= onceMaxOrder && orders.length > 0) {
|
|
325
314
|
|
|
326
315
|
const lastOrder = orders[orders.length - 1];
|
|
@@ -358,16 +347,16 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
358
347
|
throw new Error(`流动性计算错误:无法转换无限流动性数值 Liquidity calculation error: Cannot convert infinite liquidity values - ${error.message}`);
|
|
359
348
|
}
|
|
360
349
|
|
|
361
|
-
//
|
|
350
|
+
// After entering infinite liquidity, also calculate the actual amount of SOL used, until enough can be bought
|
|
362
351
|
if (result.real_lp_sol_amount === 0n) {
|
|
363
352
|
if (result.free_lp_token_amount_sum > buyTokenAmountBigInt) {
|
|
364
|
-
//
|
|
365
|
-
//
|
|
353
|
+
// At this point the gap liquidity is already enough to buy
|
|
354
|
+
// Calculate the final precise amount of token to buy
|
|
366
355
|
try {
|
|
367
356
|
const actualBuyAmount = buyTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(tokenAmount));
|
|
368
357
|
const [, preciseSol] = CurveAMM.buyFromPriceWithTokenOutput(lastEndPrice, actualBuyAmount)
|
|
369
358
|
result.real_lp_sol_amount += BigInt(preciseSol);
|
|
370
|
-
result.force_close_num = counti; //
|
|
359
|
+
result.force_close_num = counti; // Number of force closed orders
|
|
371
360
|
} catch (error) {
|
|
372
361
|
throw new Error(`流动性计算错误:无限流动性精确SOL计算失败 Liquidity calculation error: Infinite liquidity precise SOL calculation failed - ${error.message}`);
|
|
373
362
|
}
|
|
@@ -394,74 +383,63 @@ function calcLiqTokenBuy(price, buyTokenAmount, orders, onceMaxOrder, passOrder
|
|
|
394
383
|
|
|
395
384
|
|
|
396
385
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* 此函数分析卖出操作对价格区间内流动性的影响,计算可用的自由流动性、锁定流动性,
|
|
400
|
-
* 并支持跳过指定订单(将其流动性视为可用)。适用于做空订单(down_orders)场景。
|
|
386
|
+
* Calculate liquidity impact for token sell operations
|
|
387
|
+
*
|
|
401
388
|
* This function analyzes the liquidity impact of sell operations within price ranges,
|
|
402
389
|
* calculates available free liquidity, locked liquidity, and supports skipping specific
|
|
403
390
|
* orders (treating their liquidity as available). Applicable for short orders (down_orders) scenarios.
|
|
404
|
-
*
|
|
405
|
-
* @param {bigint|string|number} price -
|
|
406
|
-
* @param {bigint|string|number} sellTokenAmount -
|
|
407
|
-
* @param {Array<Object>} orders -
|
|
408
|
-
* - order_type: {number}
|
|
409
|
-
* - mint: {string}
|
|
410
|
-
* - user: {string}
|
|
411
|
-
* - lock_lp_start_price: {string} LP
|
|
412
|
-
* - lock_lp_end_price: {string} LP
|
|
413
|
-
* - lock_lp_sol_amount: {number}
|
|
414
|
-
* - lock_lp_token_amount: {number}
|
|
415
|
-
* - start_time: {number}
|
|
416
|
-
* - end_time: {number}
|
|
417
|
-
* - margin_sol_amount: {number}
|
|
418
|
-
* - borrow_amount: {number}
|
|
419
|
-
* - position_asset_amount: {number}
|
|
420
|
-
* - borrow_fee: {number}
|
|
421
|
-
* - order_pda: {string}
|
|
422
|
-
* @param {number} onceMaxOrder -
|
|
423
|
-
* @param {string|null} passOrder -
|
|
424
|
-
*
|
|
425
|
-
* @returns {Object}
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
* - free_lp_sol_amount_sum: {bigint}
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
* -
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
* -
|
|
441
|
-
*
|
|
442
|
-
* -
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
* - real_lp_sol_amount: {bigint} 实际SOL获得量,考虑真实流动性分布的精确SOL收益。0表示当前自由流动性不足以满足卖出需求,需要强平更多订单
|
|
451
|
-
* Actual SOL amount obtainable, precise SOL revenue considering real liquidity distribution. 0 means current free liquidity insufficient for sell requirement, need to force close more orders
|
|
452
|
-
*
|
|
453
|
-
* @throws {Error} 参数验证错误:price、sellTokenAmount、orders、onceMaxOrder 参数无效 Parameter validation error: invalid price, sellTokenAmount, orders, or onceMaxOrder
|
|
454
|
-
* @throws {Error} 价格转换错误:无法将价格参数转换为 BigInt Price conversion error: cannot convert price parameters to BigInt
|
|
455
|
-
* @throws {Error} 流动性计算错误:CurveAMM 计算失败或数值转换错误 Liquidity calculation error: CurveAMM calculation failure or value conversion error
|
|
456
|
-
* @throws {Error} 间隙流动性计算失败:价格间隙流动性计算异常 Gap liquidity calculation failure: price gap liquidity calculation exception
|
|
457
|
-
* @throws {Error} 无限流动性计算失败:最小价格流动性计算异常 Infinite liquidity calculation failure: min price liquidity calculation exception
|
|
458
|
-
* @throws {Error} 订单数据格式错误:订单对象缺少必需字段 Order data format error: order object missing required fields
|
|
391
|
+
*
|
|
392
|
+
* @param {bigint|string|number} price - Current token price, used as calculation start price
|
|
393
|
+
* @param {bigint|string|number} sellTokenAmount - Amount of tokens to sell, target sell amount
|
|
394
|
+
* @param {Array<Object>} orders - Array of orders sorted by lock_lp_start_price (descending):
|
|
395
|
+
* - order_type: {number} Order type (1=long, 2=short)
|
|
396
|
+
* - mint: {string} Token mint address
|
|
397
|
+
* - user: {string} User address
|
|
398
|
+
* - lock_lp_start_price: {string} LP lock start price (high price) (required)
|
|
399
|
+
* - lock_lp_end_price: {string} LP lock end price (low price) (required)
|
|
400
|
+
* - lock_lp_sol_amount: {number} Locked SOL amount (required)
|
|
401
|
+
* - lock_lp_token_amount: {number} Locked token amount (required)
|
|
402
|
+
* - start_time: {number} Start timestamp
|
|
403
|
+
* - end_time: {number} End timestamp
|
|
404
|
+
* - margin_sol_amount: {number} Margin SOL amount
|
|
405
|
+
* - borrow_amount: {number} Borrow amount
|
|
406
|
+
* - position_asset_amount: {number} Position asset amount
|
|
407
|
+
* - borrow_fee: {number} Borrow fee
|
|
408
|
+
* - order_pda: {string} Order PDA address (required for passOrder matching)
|
|
409
|
+
* @param {number} onceMaxOrder - Maximum orders to process at once, limits traversal range
|
|
410
|
+
* @param {string|null} passOrder - Order PDA address string to skip, when this value matches an order's order_pda, skip that order and count its liquidity as free liquidity
|
|
411
|
+
*
|
|
412
|
+
* @returns {Object} Liquidity calculation result object with detailed liquidity analysis data:
|
|
413
|
+
*
|
|
414
|
+
* **Free Liquidity:**
|
|
415
|
+
* - free_lp_sol_amount_sum: {bigint} Total available free liquidity SOL amount, represents SOL obtainable from selling, includes: 1) price gap liquidity 2) skipped order liquidity 3) infinite liquidity (if any)
|
|
416
|
+
* - free_lp_token_amount_sum: {bigint} Total available free liquidity token amount, represents max tokens sellable without force closing any orders
|
|
417
|
+
*
|
|
418
|
+
* **Locked Liquidity:**
|
|
419
|
+
* - lock_lp_sol_amount_sum: {bigint} Total locked liquidity SOL amount, excludes skipped orders, this liquidity is not directly usable
|
|
420
|
+
* - lock_lp_token_amount_sum: {bigint} Total locked liquidity token amount, excludes skipped orders, corresponds to locked SOL liquidity
|
|
421
|
+
*
|
|
422
|
+
* **Liquidity Status Indicators:**
|
|
423
|
+
* - has_infinite_lp: {boolean} Whether includes infinite liquidity, true means order chain ended and liquidity to min price (MIN_U128_PRICE) was calculated
|
|
424
|
+
* - pass_order_id: {number} Index of skipped order in array, -1 means no order skipped, >=0 means order at that index was skipped
|
|
425
|
+
*
|
|
426
|
+
* **Sell Execution Info:**
|
|
427
|
+
* - force_close_num: {number} Number of orders that need to be force closed, indicates how many orders need force closure to sell target amount, 0 means no force closure needed
|
|
428
|
+
* - ideal_lp_sol_amount: {bigint} Ideal SOL amount obtainable, theoretical maximum SOL revenue calculated directly from current price using CurveAMM, ignores liquidity distribution
|
|
429
|
+
* - real_lp_sol_amount: {bigint} Actual SOL amount obtainable, precise SOL revenue considering real liquidity distribution. 0 means current free liquidity insufficient for sell requirement, need to force close more orders
|
|
430
|
+
*
|
|
431
|
+
* @throws {Error} Parameter validation error: invalid price, sellTokenAmount, orders, or onceMaxOrder
|
|
432
|
+
* @throws {Error} Price conversion error: cannot convert price parameters to BigInt
|
|
433
|
+
* @throws {Error} Liquidity calculation error: CurveAMM calculation failure or value conversion error
|
|
434
|
+
* @throws {Error} Gap liquidity calculation failure: price gap liquidity calculation exception
|
|
435
|
+
* @throws {Error} Infinite liquidity calculation failure: min price liquidity calculation exception
|
|
436
|
+
* @throws {Error} Order data format error: order object missing required fields
|
|
459
437
|
*/
|
|
460
438
|
function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrder = null, initialVirtualSol = null, initialVirtualToken = null) {
|
|
461
|
-
//
|
|
462
|
-
//
|
|
439
|
+
// Since this is a sell operation, the orders are definitely in the down_orders direction lock_lp_start_price > lock_lp_end_price
|
|
440
|
+
// And lock_lp_start_price is sorted in descending order in orders
|
|
463
441
|
|
|
464
|
-
//
|
|
442
|
+
// Parameter validation
|
|
465
443
|
if (!price && price !== 0) {
|
|
466
444
|
throw new Error('参数验证错误:price 参数不能为空 Parameter validation error: price cannot be null');
|
|
467
445
|
}
|
|
@@ -479,15 +457,15 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
479
457
|
}
|
|
480
458
|
|
|
481
459
|
const result = {
|
|
482
|
-
free_lp_sol_amount_sum: 0n, //
|
|
483
|
-
free_lp_token_amount_sum: 0n, //
|
|
460
|
+
free_lp_sol_amount_sum: 0n, // Amount of SOL liquidity usable in the gaps
|
|
461
|
+
free_lp_token_amount_sum: 0n, // Amount of token liquidity usable in the gaps
|
|
484
462
|
lock_lp_sol_amount_sum: 0n,
|
|
485
463
|
lock_lp_token_amount_sum: 0n,
|
|
486
|
-
has_infinite_lp: false, //
|
|
487
|
-
pass_order_id: -1, //
|
|
488
|
-
force_close_num: 0, //
|
|
489
|
-
ideal_lp_sol_amount: 0n, //
|
|
490
|
-
real_lp_sol_amount: 0n, //
|
|
464
|
+
has_infinite_lp: false, // Whether includes infinite liquidity
|
|
465
|
+
pass_order_id: -1, // Index of skipped order
|
|
466
|
+
force_close_num: 0, // Number of force closed orders
|
|
467
|
+
ideal_lp_sol_amount: 0n, // Amount of SOL obtainable from selling sellTokenAmount under ideal conditions
|
|
468
|
+
real_lp_sol_amount: 0n, // Amount of SOL actually obtainable from selling sellTokenAmount
|
|
491
469
|
}
|
|
492
470
|
|
|
493
471
|
let sellTokenAmountBigInt;
|
|
@@ -497,10 +475,10 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
497
475
|
throw new Error(`价格转换错误:无法将 sellTokenAmount 转换为 BigInt Price conversion error: Cannot convert sellTokenAmount to BigInt - ${error.message}`);
|
|
498
476
|
}
|
|
499
477
|
|
|
500
|
-
//
|
|
478
|
+
// Declare variable for tracking the previous free liquidity total
|
|
501
479
|
let prev_free_lp_sol_amount_sum;
|
|
502
480
|
|
|
503
|
-
//
|
|
481
|
+
// Calculate the amount of SOL obtainable from selling under ideal conditions
|
|
504
482
|
try {
|
|
505
483
|
const priceBigInt = BigInt(price);
|
|
506
484
|
const initialVirtualSolDecimal = new Decimal(initialVirtualSol).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL);
|
|
@@ -513,12 +491,12 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
513
491
|
initialVirtualSolDecimal,
|
|
514
492
|
initialVirtualTokenDecimal
|
|
515
493
|
);
|
|
516
|
-
// console.log(
|
|
494
|
+
// console.log(`ideal calculation: current price=${priceBigInt}, sell token=${sellTokenAmountBigInt}, ideal SOL=${result.ideal_lp_sol_amount}`);
|
|
517
495
|
} catch (error) {
|
|
518
496
|
throw new Error(`sell流动性计算错误:理想流动性计算失败 Liquidity calculation error: Ideal liquidity calculation failed - ${error.message}`);
|
|
519
497
|
}
|
|
520
498
|
|
|
521
|
-
// orders
|
|
499
|
+
// orders length of 0 requires separate calculation
|
|
522
500
|
if (orders.length === 0) {
|
|
523
501
|
const initialVirtualSolDecimal = new Decimal(initialVirtualSol).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL);
|
|
524
502
|
const initialVirtualTokenDecimal = new Decimal(initialVirtualToken).div(CurveAMM.TOKEN_PRECISION_FACTOR_DECIMAL);
|
|
@@ -531,7 +509,7 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
531
509
|
if (sellResult) {
|
|
532
510
|
[result.free_lp_token_amount_sum, result.free_lp_sol_amount_sum] = sellResult;
|
|
533
511
|
} else {
|
|
534
|
-
//
|
|
512
|
+
// If the current price is already below the minimum price, no more can be sold
|
|
535
513
|
result.free_lp_token_amount_sum = 0n;
|
|
536
514
|
result.free_lp_sol_amount_sum = 0n;
|
|
537
515
|
}
|
|
@@ -543,15 +521,15 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
543
521
|
|
|
544
522
|
|
|
545
523
|
|
|
546
|
-
//
|
|
524
|
+
// Choose the smaller value for traversal
|
|
547
525
|
const loopCount = Math.min(orders.length, onceMaxOrder);
|
|
548
526
|
|
|
549
527
|
let counti = 0;
|
|
550
528
|
for (let i = 0; i < loopCount; i++) {
|
|
551
529
|
const order = orders[i];
|
|
552
|
-
// console.log(
|
|
530
|
+
// console.log(`processing sell order[${i}]: cumulative free Token=${result.free_lp_token_amount_sum}, target=${sellTokenAmountBigInt}, needed=${sellTokenAmountBigInt > result.free_lp_token_amount_sum}`);
|
|
553
531
|
|
|
554
|
-
//
|
|
532
|
+
// Validate order data format
|
|
555
533
|
if (!order) {
|
|
556
534
|
throw new Error(`订单数据格式错误:订单 ${i} 为空 Order data format error: Order ${i} is null`);
|
|
557
535
|
}
|
|
@@ -563,15 +541,15 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
563
541
|
}
|
|
564
542
|
|
|
565
543
|
|
|
566
|
-
//
|
|
544
|
+
// Calculate gap liquidity (sell direction: from high price to low price)
|
|
567
545
|
let startPrice, endPrice;
|
|
568
546
|
try {
|
|
569
547
|
if (i === 0) {
|
|
570
|
-
//
|
|
548
|
+
// First order: gap from current price (high) to order start price (low)
|
|
571
549
|
startPrice = BigInt(price);
|
|
572
550
|
endPrice = BigInt(order.lock_lp_start_price);
|
|
573
551
|
} else {
|
|
574
|
-
//
|
|
552
|
+
// Subsequent orders: gap from previous order end price (high) to current order start price (low)
|
|
575
553
|
startPrice = BigInt(orders[i - 1].lock_lp_end_price);
|
|
576
554
|
endPrice = BigInt(order.lock_lp_start_price);
|
|
577
555
|
}
|
|
@@ -580,7 +558,7 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
580
558
|
}
|
|
581
559
|
|
|
582
560
|
|
|
583
|
-
//
|
|
561
|
+
// If a price gap exists (when selling, startPrice should be greater than endPrice)
|
|
584
562
|
if (startPrice > endPrice) {
|
|
585
563
|
try {
|
|
586
564
|
const initialVirtualSolDecimal = new Decimal(initialVirtualSol).div(CurveAMM.SOL_PRECISION_FACTOR_DECIMAL);
|
|
@@ -595,25 +573,25 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
595
573
|
const [tokenAmount, solAmount] = gapLiquidity;
|
|
596
574
|
|
|
597
575
|
try {
|
|
598
|
-
prev_free_lp_sol_amount_sum = result.free_lp_sol_amount_sum; //
|
|
576
|
+
prev_free_lp_sol_amount_sum = result.free_lp_sol_amount_sum; // Previous value
|
|
599
577
|
result.free_lp_sol_amount_sum += BigInt(solAmount);
|
|
600
578
|
result.free_lp_token_amount_sum += BigInt(tokenAmount);
|
|
601
|
-
// console.log(
|
|
579
|
+
// console.log(`sell gap[${i}]: ${startPrice}→${endPrice}, gap Token=${tokenAmount}, gap SOL=${solAmount}, cumulative free Token=${result.free_lp_token_amount_sum}`);
|
|
602
580
|
} catch (error) {
|
|
603
581
|
throw new Error(`流动性计算错误:无法转换间隙流动性数值 Liquidity calculation error: Cannot convert gap liquidity values - ${error.message}`);
|
|
604
582
|
}
|
|
605
583
|
|
|
606
|
-
//
|
|
584
|
+
// Calculate the actual amount of SOL obtained, until enough can be sold
|
|
607
585
|
if (result.real_lp_sol_amount === 0n) {
|
|
608
586
|
if (result.free_lp_token_amount_sum >= sellTokenAmountBigInt) {
|
|
609
|
-
//
|
|
610
|
-
//
|
|
587
|
+
// At this point the gap liquidity is already enough to sell
|
|
588
|
+
// Calculate the precise amount of SOL obtainable
|
|
611
589
|
try {
|
|
612
590
|
const actualSellAmount = sellTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(tokenAmount));
|
|
613
591
|
const [, preciseSol] = CurveAMM.sellFromPriceWithTokenInput(startPrice, actualSellAmount);
|
|
614
592
|
result.real_lp_sol_amount = prev_free_lp_sol_amount_sum + preciseSol;
|
|
615
|
-
// console.log(
|
|
616
|
-
result.force_close_num = counti; //
|
|
593
|
+
// console.log(`sell actual calculation[${i}]: free liquidity sufficient, actualSellAmount=${actualSellAmount}, preciseSol=${preciseSol}, actual SOL=${result.real_lp_sol_amount}`);
|
|
594
|
+
result.force_close_num = counti; // Number of force closed orders
|
|
617
595
|
} catch (error) {
|
|
618
596
|
throw new Error(`流动性计算错误:精确SOL计算失败 Liquidity calculation error: Precise SOL calculation failed - ${error.message}`);
|
|
619
597
|
}
|
|
@@ -632,11 +610,11 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
632
610
|
} else {
|
|
633
611
|
}
|
|
634
612
|
|
|
635
|
-
//
|
|
613
|
+
// Check whether this order needs to be skipped (passOrder logic)
|
|
636
614
|
|
|
637
615
|
if (passOrder == order.order_pda) {
|
|
638
616
|
|
|
639
|
-
//
|
|
617
|
+
// Add the skipped order's liquidity to the free liquidity
|
|
640
618
|
try {
|
|
641
619
|
if (order.lock_lp_sol_amount === undefined || order.lock_lp_sol_amount === null) {
|
|
642
620
|
throw new Error(`订单数据格式错误:跳过订单 ${i} 缺少 lock_lp_sol_amount Order data format error: Skipped order ${i} missing lock_lp_sol_amount`);
|
|
@@ -645,19 +623,19 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
645
623
|
throw new Error(`订单数据格式错误:跳过订单 ${i} 缺少 lock_lp_token_amount Order data format error: Skipped order ${i} missing lock_lp_token_amount`);
|
|
646
624
|
}
|
|
647
625
|
|
|
648
|
-
const prevFreeSolSum = result.free_lp_sol_amount_sum; //
|
|
626
|
+
const prevFreeSolSum = result.free_lp_sol_amount_sum; // Save the previous value for calculation
|
|
649
627
|
result.free_lp_sol_amount_sum += BigInt(order.lock_lp_sol_amount);
|
|
650
628
|
result.free_lp_token_amount_sum += BigInt(order.lock_lp_token_amount);
|
|
651
629
|
|
|
652
630
|
result.pass_order_id = i;
|
|
653
631
|
|
|
654
632
|
|
|
655
|
-
//
|
|
633
|
+
// Check whether the free liquidity after skipping the order already meets the sell requirement
|
|
656
634
|
if (result.real_lp_sol_amount === 0n) {
|
|
657
635
|
if (result.free_lp_token_amount_sum >= sellTokenAmountBigInt) {
|
|
658
|
-
//
|
|
636
|
+
// Free liquidity is already enough for the sell requirement
|
|
659
637
|
try {
|
|
660
|
-
//
|
|
638
|
+
// Calculate the precise amount of SOL obtainable
|
|
661
639
|
const targetPrice = i === 0 ? BigInt(price) : BigInt(orders[i - 1].lock_lp_end_price);
|
|
662
640
|
const actualSellAmount = sellTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(order.lock_lp_token_amount));
|
|
663
641
|
const [, preciseSol] = CurveAMM.sellFromPriceWithTokenInput(targetPrice, actualSellAmount);
|
|
@@ -676,7 +654,7 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
676
654
|
throw new Error(`流动性计算错误:无法处理跳过订单 ${i} 的流动性 Liquidity calculation error: Cannot process skipped order ${i} liquidity - ${error.message}`);
|
|
677
655
|
}
|
|
678
656
|
} else {
|
|
679
|
-
//
|
|
657
|
+
// Accumulate locked liquidity (normal case)
|
|
680
658
|
try {
|
|
681
659
|
if (order.lock_lp_sol_amount === undefined || order.lock_lp_sol_amount === null) {
|
|
682
660
|
throw new Error(`订单数据格式错误:订单 ${i} 缺少 lock_lp_sol_amount Order data format error: Order ${i} missing lock_lp_sol_amount`);
|
|
@@ -699,7 +677,7 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
699
677
|
|
|
700
678
|
}
|
|
701
679
|
|
|
702
|
-
//
|
|
680
|
+
// If the number of traversed orders is less than or equal to onceMaxOrder, the chain has ended and infinite liquidity needs to be calculated
|
|
703
681
|
if (orders.length <= onceMaxOrder && orders.length > 0) {
|
|
704
682
|
|
|
705
683
|
const lastOrder = orders[orders.length - 1];
|
|
@@ -740,15 +718,15 @@ function calcLiqTokenSell(price, sellTokenAmount, orders, onceMaxOrder, passOrde
|
|
|
740
718
|
throw new Error(`流动性计算错误:无法转换无限流动性数值 Liquidity calculation error: Cannot convert infinite liquidity values - ${error.message}`);
|
|
741
719
|
}
|
|
742
720
|
|
|
743
|
-
//
|
|
721
|
+
// After entering infinite liquidity, calculate the actual amount of SOL obtained
|
|
744
722
|
if (result.real_lp_sol_amount === 0n) {
|
|
745
723
|
if (result.free_lp_token_amount_sum >= sellTokenAmountBigInt) {
|
|
746
|
-
//
|
|
724
|
+
// Infinite liquidity is enough for the sell requirement
|
|
747
725
|
try {
|
|
748
726
|
const actualSellAmount = sellTokenAmountBigInt - (result.free_lp_token_amount_sum - BigInt(tokenAmount));
|
|
749
727
|
const [, preciseSol] = CurveAMM.sellFromPriceWithTokenInput(lastEndPrice, actualSellAmount);
|
|
750
728
|
result.real_lp_sol_amount = prevFreeSolSum + preciseSol;
|
|
751
|
-
result.force_close_num = counti; //
|
|
729
|
+
result.force_close_num = counti; // Number of force closed orders
|
|
752
730
|
} catch (error) {
|
|
753
731
|
throw new Error(`流动性计算错误:无限流动性精确SOL计算失败 Liquidity calculation error: Infinite liquidity precise SOL calculation failed - ${error.message}`);
|
|
754
732
|
}
|