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
|
@@ -23,8 +23,8 @@ function transformOrdersData(ordersData) {
|
|
|
23
23
|
lock_lp_end_price: BigInt(order.lock_lp_end_price),
|
|
24
24
|
lock_lp_sol_amount: order.lock_lp_sol_amount,
|
|
25
25
|
lock_lp_token_amount: order.lock_lp_token_amount,
|
|
26
|
-
index: order.index, //
|
|
27
|
-
order_id: order.order_id //
|
|
26
|
+
index: order.index, // Preserve the index in the OrderBook
|
|
27
|
+
order_id: order.order_id // Preserve the order ID
|
|
28
28
|
}));
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -33,164 +33,164 @@ function transformOrdersData(ordersData) {
|
|
|
33
33
|
* @property {number} order_type - Order type (e.g., 1 for down_orders, 2 for up_orders).
|
|
34
34
|
* @property {bigint} lock_lp_start_price - Locked liquidity start price.
|
|
35
35
|
* @property {bigint} lock_lp_end_price - Locked liquidity end price.
|
|
36
|
-
* @property {number} lock_lp_sol_amount -
|
|
37
|
-
* @property {number} lock_lp_token_amount -
|
|
36
|
+
* @property {number} lock_lp_sol_amount - Locked SOL amount.
|
|
37
|
+
* @property {number} lock_lp_token_amount - Locked token amount.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* @typedef {Object} OverlapResult
|
|
42
|
-
* @property {boolean} no_overlap -
|
|
43
|
-
* @property {number[]} close_insert_indices -
|
|
44
|
-
* @property {string} overlap_reason -
|
|
42
|
+
* @property {boolean} no_overlap - Whether there is no overlap. `true` means no overlap (safe to insert), `false` means there is an overlap.
|
|
43
|
+
* @property {number[]} close_insert_indices - Array of position indices for inserting into the order book when closing. Contains the main position index and the indices of the 3 nodes before and after it.
|
|
44
|
+
* @property {string} overlap_reason - Description of the overlap reason. Empty string when there is no overlap, otherwise describes the specific reason.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Checks whether the given price range overlaps with any range in the sorted order list, and returns a suitable insertion position index.
|
|
49
49
|
*
|
|
50
|
-
* ##
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* ## Description
|
|
51
|
+
* This function is used in margin trading (long/short) scenarios, where the position to insert the closing order into the order book (OrderBook) needs to be determined when opening a position.
|
|
52
|
+
* The function checks whether the new order's price range overlaps with existing orders, and returns multiple candidate insertion position indices to improve the contract execution success rate.
|
|
53
53
|
*
|
|
54
|
-
* ##
|
|
55
|
-
* 1.
|
|
56
|
-
* 2.
|
|
57
|
-
* -
|
|
58
|
-
* -
|
|
59
|
-
* 3.
|
|
60
|
-
* -
|
|
61
|
-
* -
|
|
62
|
-
* -
|
|
54
|
+
* ## Core Logic
|
|
55
|
+
* 1. **Price range check**: Use a binary search algorithm to find a suitable insertion position in the sorted order list
|
|
56
|
+
* 2. **Overlap detection**:
|
|
57
|
+
* - Basic overlap: the new range directly overlaps with the price range of an existing order
|
|
58
|
+
* - Liquidity reservation overlap: considering the liquidity reservation area (default 100%), to prevent price ranges from being too close
|
|
59
|
+
* 3. **Candidate index generation**:
|
|
60
|
+
* - Main insertion position: the logically most suitable insertion position index
|
|
61
|
+
* - Alternative positions: the indices of several nodes before and after that position (the count is determined by the MAX_CANDIDATE_INDICES constant)
|
|
62
|
+
* - Purpose: even if the order at the main position is deleted or moved, the contract can still find another suitable position
|
|
63
63
|
*
|
|
64
|
-
* ##
|
|
65
|
-
* -
|
|
66
|
-
* -
|
|
67
|
-
* -
|
|
68
|
-
* -
|
|
69
|
-
* -
|
|
64
|
+
* ## Return Value Description
|
|
65
|
+
* - **When no overlap**: returns the `close_insert_indices` array, containing the OrderBook indices of candidate insertion positions
|
|
66
|
+
* - Priority: main position → 1 before → 1 after → 2 before → 2 after → ... → N before → N after
|
|
67
|
+
* - The number of indices is determined by the MAX_CANDIDATE_INDICES constant (default 21, i.e. main position + 10 before + 10 after)
|
|
68
|
+
* - **When there is overlap**: returns an empty array `[]`, indicating insertion is not possible
|
|
69
|
+
* - **Empty order book**: returns `[65535]` (u16::MAX), indicating insertion at the head
|
|
70
70
|
*
|
|
71
|
-
* ##
|
|
72
|
-
* - **down_orders
|
|
73
|
-
* - lock_lp_start_price > lock_lp_end_price
|
|
74
|
-
* -
|
|
75
|
-
* - **up_orders
|
|
76
|
-
* - lock_lp_start_price < lock_lp_end_price
|
|
77
|
-
* -
|
|
71
|
+
* ## Order Type Rules
|
|
72
|
+
* - **down_orders (long orders)**: prices sorted from high to low
|
|
73
|
+
* - lock_lp_start_price > lock_lp_end_price (price falling)
|
|
74
|
+
* - the new order's end_price must be >= the next order's start_price
|
|
75
|
+
* - **up_orders (short orders)**: prices sorted from low to high
|
|
76
|
+
* - lock_lp_start_price < lock_lp_end_price (price rising)
|
|
77
|
+
* - the new order's end_price must be <= the next order's start_price
|
|
78
78
|
*
|
|
79
|
-
* @param {'down_orders' | 'up_orders'} order_type -
|
|
80
|
-
* - 'down_orders':
|
|
81
|
-
* - 'up_orders':
|
|
79
|
+
* @param {'down_orders' | 'up_orders'} order_type - Order type
|
|
80
|
+
* - 'down_orders': long orders, prices sorted from high to low
|
|
81
|
+
* - 'up_orders': short orders, prices sorted from low to high
|
|
82
82
|
*
|
|
83
|
-
* @param {Order[]} order_list -
|
|
84
|
-
* -
|
|
85
|
-
* - `index` {number}:
|
|
86
|
-
* - `lock_lp_start_price` {bigint|string}:
|
|
87
|
-
* - `lock_lp_end_price` {bigint|string}:
|
|
88
|
-
* -
|
|
89
|
-
* -
|
|
83
|
+
* @param {Order[]} order_list - Sorted array of order objects
|
|
84
|
+
* - Each order must contain the following fields:
|
|
85
|
+
* - `index` {number}: the original index value of the order in the OrderBook (this is the key field required by the contract)
|
|
86
|
+
* - `lock_lp_start_price` {bigint|string}: the start price of the locked liquidity pool range
|
|
87
|
+
* - `lock_lp_end_price` {bigint|string}: the end price of the locked liquidity pool range
|
|
88
|
+
* - The array must already be sorted by price (down_orders from high to low, up_orders from low to high)
|
|
89
|
+
* - Usually comes from the data returned by `sdk.chain.orders()` or `sdk.fast.orders()`
|
|
90
90
|
*
|
|
91
|
-
* @param {bigint | number | string} lp_start_price -
|
|
92
|
-
* -
|
|
93
|
-
* -
|
|
91
|
+
* @param {bigint | number | string} lp_start_price - The start price of the new order
|
|
92
|
+
* - For down_orders: this is the higher price (near the opening price)
|
|
93
|
+
* - For up_orders: this is the lower price (near the stop loss price)
|
|
94
94
|
*
|
|
95
|
-
* @param {bigint | number | string} lp_end_price -
|
|
96
|
-
* -
|
|
97
|
-
* -
|
|
95
|
+
* @param {bigint | number | string} lp_end_price - The end price of the new order
|
|
96
|
+
* - For down_orders: this is the lower price (near the stop loss price)
|
|
97
|
+
* - For up_orders: this is the higher price (near the opening price)
|
|
98
98
|
*
|
|
99
|
-
* @returns {OverlapResult}
|
|
100
|
-
* @returns {boolean} returns.no_overlap -
|
|
101
|
-
* - `true`:
|
|
102
|
-
* - `false`:
|
|
103
|
-
* @returns {number[]} returns.close_insert_indices -
|
|
104
|
-
* -
|
|
105
|
-
* -
|
|
106
|
-
* -
|
|
107
|
-
* @returns {string} returns.overlap_reason -
|
|
108
|
-
* -
|
|
109
|
-
* -
|
|
99
|
+
* @returns {OverlapResult} Returns an object containing the overlap check result and candidate insertion indices
|
|
100
|
+
* @returns {boolean} returns.no_overlap - Whether there is no overlap
|
|
101
|
+
* - `true`: safe to insert, use the indices in `close_insert_indices`
|
|
102
|
+
* - `false`: there is an overlap, cannot insert
|
|
103
|
+
* @returns {number[]} returns.close_insert_indices - Array of OrderBook indices for candidate insertion positions
|
|
104
|
+
* - When no overlap: contains the main position and the indices of the 3 nodes before and after (up to 7)
|
|
105
|
+
* - When there is overlap: empty array `[]`
|
|
106
|
+
* - When order book is empty: `[65535]` indicates insertion at the head
|
|
107
|
+
* @returns {string} returns.overlap_reason - Description of the overlap reason
|
|
108
|
+
* - When no overlap: empty string `""`
|
|
109
|
+
* - When there is overlap: describes the specific reason (e.g. "Overlaps with existing order range")
|
|
110
110
|
*
|
|
111
111
|
* @example
|
|
112
|
-
* //
|
|
112
|
+
* // Example 1: down_orders (long orders) - insert into the middle position
|
|
113
113
|
* const downOrders = [
|
|
114
|
-
* { index: 10, lock_lp_start_price: 100n, lock_lp_end_price: 90n }, //
|
|
115
|
-
* { index: 25, lock_lp_start_price: 80n, lock_lp_end_price: 70n }, //
|
|
116
|
-
* { index: 33, lock_lp_start_price: 60n, lock_lp_end_price: 50n } //
|
|
114
|
+
* { index: 10, lock_lp_start_price: 100n, lock_lp_end_price: 90n }, // Order 1
|
|
115
|
+
* { index: 25, lock_lp_start_price: 80n, lock_lp_end_price: 70n }, // Order 2
|
|
116
|
+
* { index: 33, lock_lp_start_price: 60n, lock_lp_end_price: 50n } // Order 3
|
|
117
117
|
* ];
|
|
118
118
|
*
|
|
119
|
-
* //
|
|
119
|
+
* // Check whether the new order [75, 72] can be inserted
|
|
120
120
|
* const result = checkPriceRangeOverlap('down_orders', downOrders, 75n, 72n);
|
|
121
121
|
* console.log(result);
|
|
122
|
-
* //
|
|
122
|
+
* // Returns: {
|
|
123
123
|
* // no_overlap: true,
|
|
124
124
|
* // close_insert_indices: [25, 10, 33],
|
|
125
|
-
* // //
|
|
126
|
-
* // //
|
|
125
|
+
* // // The main position is 25 (Order 2), because the new order should be inserted between Order 2 and Order 3
|
|
126
|
+
* // // Alternative positions: 10 (Order 1 before), 33 (Order 3 after)
|
|
127
127
|
* // overlap_reason: ""
|
|
128
128
|
* // }
|
|
129
129
|
*
|
|
130
130
|
* @example
|
|
131
|
-
* //
|
|
131
|
+
* // Example 2: down_orders - price overlap case
|
|
132
132
|
* const downOrders = [
|
|
133
133
|
* { index: 10, lock_lp_start_price: 100n, lock_lp_end_price: 90n },
|
|
134
134
|
* { index: 25, lock_lp_start_price: 80n, lock_lp_end_price: 70n }
|
|
135
135
|
* ];
|
|
136
136
|
*
|
|
137
|
-
* //
|
|
137
|
+
* // New order [95, 85] overlaps with Order 1 [100, 90]
|
|
138
138
|
* const result = checkPriceRangeOverlap('down_orders', downOrders, 95n, 85n);
|
|
139
139
|
* console.log(result);
|
|
140
|
-
* //
|
|
140
|
+
* // Returns: {
|
|
141
141
|
* // no_overlap: false,
|
|
142
142
|
* // close_insert_indices: [],
|
|
143
143
|
* // overlap_reason: "Overlaps with existing order range"
|
|
144
144
|
* // }
|
|
145
145
|
*
|
|
146
146
|
* @example
|
|
147
|
-
* //
|
|
147
|
+
* // Example 3: up_orders (short orders) - insert at the end
|
|
148
148
|
* const upOrders = [
|
|
149
149
|
* { index: 5, lock_lp_start_price: 70n, lock_lp_end_price: 80n },
|
|
150
150
|
* { index: 12, lock_lp_start_price: 90n, lock_lp_end_price: 100n }
|
|
151
151
|
* ];
|
|
152
152
|
*
|
|
153
|
-
* //
|
|
153
|
+
* // New order [110, 120] should be inserted at the end
|
|
154
154
|
* const result = checkPriceRangeOverlap('up_orders', upOrders, 110n, 120n);
|
|
155
155
|
* console.log(result);
|
|
156
|
-
* //
|
|
156
|
+
* // Returns: {
|
|
157
157
|
* // no_overlap: true,
|
|
158
158
|
* // close_insert_indices: [12, 5],
|
|
159
|
-
* // //
|
|
160
|
-
* // //
|
|
159
|
+
* // // The main position is 12 (Order 2), because the new order should be inserted after Order 2
|
|
160
|
+
* // // Alternative positions: 5 (Order 1 before)
|
|
161
161
|
* // overlap_reason: ""
|
|
162
162
|
* // }
|
|
163
163
|
*
|
|
164
164
|
* @example
|
|
165
|
-
* //
|
|
165
|
+
* // Example 4: empty order book - the first order
|
|
166
166
|
* const emptyOrders = [];
|
|
167
167
|
* const result = checkPriceRangeOverlap('down_orders', emptyOrders, 100n, 90n);
|
|
168
168
|
* console.log(result);
|
|
169
|
-
* //
|
|
169
|
+
* // Returns: {
|
|
170
170
|
* // no_overlap: true,
|
|
171
171
|
* // close_insert_indices: [65535],
|
|
172
|
-
* // // 65535
|
|
172
|
+
* // // 65535 is u16::MAX, indicating insertion at the head (special value when the order book is empty)
|
|
173
173
|
* // overlap_reason: ""
|
|
174
174
|
* // }
|
|
175
175
|
*
|
|
176
176
|
* @example
|
|
177
|
-
* //
|
|
177
|
+
* // Example 5: actual usage scenario - long trade
|
|
178
178
|
* async function openLongPosition(sdk, mint, buyTokenAmount, stopLossPrice) {
|
|
179
|
-
* // 1.
|
|
179
|
+
* // 1. Get down_orders data
|
|
180
180
|
* const ordersData = await sdk.data.orders(mint, { type: 'down_orders' });
|
|
181
181
|
* const orders = ordersData.data.orders;
|
|
182
182
|
*
|
|
183
|
-
* // 2.
|
|
183
|
+
* // 2. Get the current price
|
|
184
184
|
* const currentPrice = BigInt(await sdk.data.price(mint));
|
|
185
185
|
*
|
|
186
|
-
* // 3.
|
|
186
|
+
* // 3. Calculate the closing price range (simulation)
|
|
187
187
|
* const simulateResult = await sdk.simulator.simulateLongStopLoss(
|
|
188
188
|
* mint,
|
|
189
189
|
* buyTokenAmount,
|
|
190
190
|
* stopLossPrice
|
|
191
191
|
* );
|
|
192
192
|
*
|
|
193
|
-
* // 4.
|
|
193
|
+
* // 4. Check whether the price range can be inserted
|
|
194
194
|
* const overlapCheck = checkPriceRangeOverlap(
|
|
195
195
|
* 'down_orders',
|
|
196
196
|
* orders,
|
|
@@ -199,29 +199,29 @@ function transformOrdersData(ordersData) {
|
|
|
199
199
|
* );
|
|
200
200
|
*
|
|
201
201
|
* if (!overlapCheck.no_overlap) {
|
|
202
|
-
* throw new Error(
|
|
202
|
+
* throw new Error(`Unable to open position: ${overlapCheck.overlap_reason}`);
|
|
203
203
|
* }
|
|
204
204
|
*
|
|
205
|
-
* // 5.
|
|
205
|
+
* // 5. Use close_insert_indices to call the contract
|
|
206
206
|
* const tx = await sdk.trading.long({
|
|
207
207
|
* mint,
|
|
208
208
|
* buyTokenAmount,
|
|
209
209
|
* maxSolAmount,
|
|
210
210
|
* marginSolMax,
|
|
211
211
|
* closePrice: stopLossPrice,
|
|
212
|
-
* closeInsertIndices: overlapCheck.close_insert_indices //
|
|
212
|
+
* closeInsertIndices: overlapCheck.close_insert_indices // Passed to the contract
|
|
213
213
|
* });
|
|
214
214
|
*
|
|
215
215
|
* return tx;
|
|
216
216
|
* }
|
|
217
217
|
*
|
|
218
|
-
* @throws {Error}
|
|
218
|
+
* @throws {Error} Throws an error when the input start and end prices do not match the order type rules
|
|
219
219
|
*
|
|
220
|
-
* @see {@link https://github.com/your-repo/docs/orderbook.md|OrderBook
|
|
221
|
-
* @see {@link transformOrdersData}
|
|
220
|
+
* @see {@link https://github.com/your-repo/docs/orderbook.md|OrderBook documentation}
|
|
221
|
+
* @see {@link transformOrdersData} Data format transformation function
|
|
222
222
|
*
|
|
223
223
|
* @since 2.0.0
|
|
224
|
-
* @version 2.0.0 -
|
|
224
|
+
* @version 2.0.0 - Changed from returning prev_order_pda/next_order_pda to returning close_insert_indices
|
|
225
225
|
*/
|
|
226
226
|
function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_price) {
|
|
227
227
|
// console.log("checkPriceRangeOverlap=",order_type,lp_start_price, lp_end_price)
|
|
@@ -236,7 +236,7 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
236
236
|
|
|
237
237
|
const isDown = order_type === 'down_orders';
|
|
238
238
|
|
|
239
|
-
//
|
|
239
|
+
// Validate and normalize the input price range, ensuring minPrice <= maxPrice
|
|
240
240
|
if ((isDown && startPrice < endPrice) || (!isDown && startPrice > endPrice)) {
|
|
241
241
|
throw new Error('输入的起始和结束价格与订单类型规则不匹配。');
|
|
242
242
|
}
|
|
@@ -245,7 +245,7 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
245
245
|
|
|
246
246
|
let low = 0;
|
|
247
247
|
let high = order_list.length - 1;
|
|
248
|
-
let insertionIndex = order_list.length; //
|
|
248
|
+
let insertionIndex = order_list.length; // Default to inserting at the end
|
|
249
249
|
|
|
250
250
|
while (low <= high) {
|
|
251
251
|
const mid = Math.floor((low + high) / 2);
|
|
@@ -256,9 +256,9 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
256
256
|
const orderMin = isDown ? orderEnd : orderStart;
|
|
257
257
|
const orderMax = isDown ? orderStart : orderEnd;
|
|
258
258
|
|
|
259
|
-
//
|
|
259
|
+
// Core overlap check: (StartA < EndB) and (EndA > StartB)
|
|
260
260
|
if (minPrice < orderMax && maxPrice > orderMin) {
|
|
261
|
-
//
|
|
261
|
+
// Basic overlap occurred
|
|
262
262
|
return {
|
|
263
263
|
no_overlap: false,
|
|
264
264
|
close_insert_indices: [],
|
|
@@ -267,16 +267,16 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
267
267
|
}
|
|
268
268
|
|
|
269
269
|
if (isDown) {
|
|
270
|
-
// down_orders:
|
|
271
|
-
if (maxPrice > orderMax) { //
|
|
270
|
+
// down_orders: prices from high to low (orderMax decreasing)
|
|
271
|
+
if (maxPrice > orderMax) { // The new range is to the "left" of the current range (higher price)
|
|
272
272
|
insertionIndex = mid;
|
|
273
273
|
high = mid - 1;
|
|
274
274
|
} else {
|
|
275
275
|
low = mid + 1;
|
|
276
276
|
}
|
|
277
277
|
} else {
|
|
278
|
-
// up_orders:
|
|
279
|
-
if (minPrice < orderMin) { //
|
|
278
|
+
// up_orders: prices from low to high (orderMin increasing)
|
|
279
|
+
if (minPrice < orderMin) { // The new range is to the "left" of the current range (lower price)
|
|
280
280
|
insertionIndex = mid;
|
|
281
281
|
high = mid - 1;
|
|
282
282
|
} else {
|
|
@@ -285,12 +285,12 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
//
|
|
289
|
-
// insertionIndex
|
|
288
|
+
// Based on the found insertion point, determine the logical previous and next orders
|
|
289
|
+
// insertionIndex is the position where the new range should be inserted so the list remains sorted
|
|
290
290
|
const nextOrder = order_list[insertionIndex] || null;
|
|
291
291
|
const prevOrder = order_list[insertionIndex - 1] || null;
|
|
292
292
|
|
|
293
|
-
//
|
|
293
|
+
// Check liquidity reservation overlap
|
|
294
294
|
function checkLiquidityReservationOverlap(checkOrder) {
|
|
295
295
|
if (!checkOrder) return false;
|
|
296
296
|
|
|
@@ -299,16 +299,16 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
299
299
|
const orderMin = isDown ? orderEnd : orderStart;
|
|
300
300
|
const orderMax = isDown ? orderStart : orderEnd;
|
|
301
301
|
|
|
302
|
-
//
|
|
302
|
+
// Calculate the expanded range value
|
|
303
303
|
const expansionAmount = (orderMax - orderMin) * BigInt(Math.floor(LIQUIDITY_RESERVATION)) / 100n;
|
|
304
304
|
|
|
305
305
|
let hasOverlap;
|
|
306
306
|
if (isDown) {
|
|
307
|
-
// down_orders: start
|
|
307
|
+
// down_orders: start unchanged, end expands downward
|
|
308
308
|
const expandedEnd = orderMin - expansionAmount;
|
|
309
309
|
hasOverlap = startPrice >= expandedEnd;
|
|
310
310
|
} else {
|
|
311
|
-
// up_orders: start
|
|
311
|
+
// up_orders: start unchanged, end expands upward
|
|
312
312
|
const expandedEnd = orderMax + expansionAmount;
|
|
313
313
|
hasOverlap = startPrice <= expandedEnd;
|
|
314
314
|
}
|
|
@@ -316,7 +316,7 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
316
316
|
return hasOverlap;
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
//
|
|
319
|
+
// Check liquidity reservation overlap with the previous order
|
|
320
320
|
if (prevOrder && checkLiquidityReservationOverlap(prevOrder)) {
|
|
321
321
|
return {
|
|
322
322
|
no_overlap: false,
|
|
@@ -325,39 +325,39 @@ function checkPriceRangeOverlap(order_type, order_list, lp_start_price, lp_end_p
|
|
|
325
325
|
};
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
//
|
|
329
|
-
//
|
|
328
|
+
// No overlap, build the close_insert_indices array
|
|
329
|
+
// Priority: main position → 1 before → 1 after → 2 before → 2 after → 3 before → 3 after
|
|
330
330
|
const indices = [];
|
|
331
331
|
|
|
332
|
-
//
|
|
333
|
-
// - down_orders (
|
|
334
|
-
// -
|
|
335
|
-
// -
|
|
336
|
-
// - up_orders (
|
|
337
|
-
// -
|
|
338
|
-
// -
|
|
332
|
+
// Main insertion position logic:
|
|
333
|
+
// - down_orders (prices high to low): insert after prevOrder
|
|
334
|
+
// - If there is no prevOrder (insertionIndex=0), the price is the highest, use u16::MAX to insert at the head
|
|
335
|
+
// - If there is a prevOrder, use prevOrder.index, insert after it
|
|
336
|
+
// - up_orders (prices low to high): insert after prevOrder
|
|
337
|
+
// - If there is no prevOrder (insertionIndex=0), the price is the lowest, use u16::MAX to insert at the head
|
|
338
|
+
// - If there is a prevOrder, use prevOrder.index, insert after it
|
|
339
339
|
|
|
340
340
|
if (prevOrder && prevOrder.index !== undefined) {
|
|
341
|
-
//
|
|
341
|
+
// There is a previous order, insert after it
|
|
342
342
|
indices.push(prevOrder.index);
|
|
343
343
|
} else {
|
|
344
|
-
//
|
|
345
|
-
// down_orders:
|
|
346
|
-
// up_orders:
|
|
347
|
-
indices.push(65535); // u16::MAX -
|
|
344
|
+
// No previous order (insertionIndex=0)
|
|
345
|
+
// down_orders: highest price, insert at the head (65535)
|
|
346
|
+
// up_orders: lowest price, insert at the head (65535)
|
|
347
|
+
indices.push(65535); // u16::MAX - insert at the head
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
//
|
|
351
|
-
//
|
|
350
|
+
// Add the indices of the nodes before and after
|
|
351
|
+
// Calculate how many before/after nodes to add based on the MAX_CANDIDATE_INDICES constant
|
|
352
352
|
for (let offset = 1; offset <= CANDIDATE_NODES_EACH_SIDE; offset++) {
|
|
353
|
-
//
|
|
353
|
+
// Add the offset-th node before
|
|
354
354
|
const beforeIndex = insertionIndex - 1 - offset;
|
|
355
355
|
if (beforeIndex >= 0 && order_list[beforeIndex] && order_list[beforeIndex].index !== undefined) {
|
|
356
356
|
indices.push(order_list[beforeIndex].index);
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
-
//
|
|
360
|
-
// offset=1
|
|
359
|
+
// Add the offset-th node after
|
|
360
|
+
// offset=1 should be nextOrder (insertionIndex), offset=2 is insertionIndex+1, and so on
|
|
361
361
|
const afterIndex = insertionIndex + offset - 1;
|
|
362
362
|
if (afterIndex < order_list.length && order_list[afterIndex] && order_list[afterIndex].index !== undefined) {
|
|
363
363
|
indices.push(order_list[afterIndex].index);
|
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
const LIQUIDITY_RESERVATION = 100; // 100%
|
|
5
5
|
|
|
6
6
|
// Price adjustment percentage
|
|
7
|
-
const PRICE_ADJUSTMENT_PERCENTAGE = 15; // 5
|
|
7
|
+
const PRICE_ADJUSTMENT_PERCENTAGE = 15; // 5 means 0.5%
|
|
8
8
|
|
|
9
9
|
// Minimum stop loss percentage - stop loss price must be at least this far from current price
|
|
10
|
-
// 最小止损百分比 - 止损价格必须与当前价格至少相差此百分比
|
|
11
10
|
// Example: 40 means 4.0% (calculation: 40/1000 = 0.04 = 4%)
|
|
12
11
|
const MIN_STOP_LOSS_PERCENT = 40; // 4.0%
|
|
13
12
|
|
package/src/modules/simulator.js
CHANGED
|
@@ -21,10 +21,9 @@ class SimulatorModule {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Simulate token buy transaction - calculate if target token amount can be purchased
|
|
24
|
-
*
|
|
25
|
-
* @param {string}
|
|
26
|
-
* @param {
|
|
27
|
-
* @param {string} passOrder - Optional order address to skip (won't be liquidated) 可选的跳过订单地址
|
|
24
|
+
* @param {string} mint - Token address
|
|
25
|
+
* @param {bigint|string|number} buyTokenAmount - Target token amount to buy
|
|
26
|
+
* @param {string} passOrder - Optional order address to skip (won't be liquidated)
|
|
28
27
|
* @param {Object|null} lastPrice - Token price info, default null
|
|
29
28
|
* @param {Object|null} ordersData - Orders response object, default null
|
|
30
29
|
* @returns {Promise<Object>} Token buy simulation result with the following structure:
|
|
@@ -51,7 +50,7 @@ class SimulatorModule {
|
|
|
51
50
|
* Simulate token sell transaction analysis
|
|
52
51
|
* @param {string} mint - Token address
|
|
53
52
|
* @param {bigint|string|number} sellTokenAmount - Token amount to sell (u64 format, precision 10^9)
|
|
54
|
-
* @param {string} passOrder - Optional order address to skip (won't be liquidated)
|
|
53
|
+
* @param {string} passOrder - Optional order address to skip (won't be liquidated)
|
|
55
54
|
* @param {Object|null} lastPrice - Token price info, default null
|
|
56
55
|
* @param {Object|null} ordersData - Orders response object, default null
|
|
57
56
|
* @returns {Promise<Object>} Token sell simulation result with the following structure:
|
|
@@ -130,11 +129,10 @@ class SimulatorModule {
|
|
|
130
129
|
|
|
131
130
|
/**
|
|
132
131
|
* Generate candidate insertion indices for closing long position
|
|
133
|
-
*
|
|
134
|
-
* @param {string}
|
|
135
|
-
* @param {
|
|
136
|
-
* @
|
|
137
|
-
* @returns {Promise<Object>} Result containing closeOrderIndices array 包含候选索引数组的结果
|
|
132
|
+
* @param {string} mint - Token address
|
|
133
|
+
* @param {number|string|anchor.BN} closeOrderId - Order ID to close (order_id, not index)
|
|
134
|
+
* @param {Object|null} ordersData - Orders data (optional)
|
|
135
|
+
* @returns {Promise<Object>} Result containing closeOrderIndices array
|
|
138
136
|
*/
|
|
139
137
|
async simulateLongClose(mint, closeOrderId, ordersData = null) {
|
|
140
138
|
return simulateLongClose.call(this, mint, closeOrderId, ordersData);
|
|
@@ -142,11 +140,10 @@ class SimulatorModule {
|
|
|
142
140
|
|
|
143
141
|
/**
|
|
144
142
|
* Generate candidate insertion indices for closing short position
|
|
145
|
-
*
|
|
146
|
-
* @param {string}
|
|
147
|
-
* @param {
|
|
148
|
-
* @
|
|
149
|
-
* @returns {Promise<Object>} Result containing closeOrderIndices array 包含候选索引数组的结果
|
|
143
|
+
* @param {string} mint - Token address
|
|
144
|
+
* @param {number|string|anchor.BN} closeOrderId - Order ID to close (order_id, not index)
|
|
145
|
+
* @param {Object|null} ordersData - Orders data (optional)
|
|
146
|
+
* @returns {Promise<Object>} Result containing closeOrderIndices array
|
|
150
147
|
*/
|
|
151
148
|
async simulateShortClose(mint, closeOrderId, ordersData = null) {
|
|
152
149
|
return simulateShortClose.call(this, mint, closeOrderId, ordersData);
|
|
@@ -154,8 +151,7 @@ class SimulatorModule {
|
|
|
154
151
|
|
|
155
152
|
/**
|
|
156
153
|
* Simulate buy transaction with SOL amount input
|
|
157
|
-
*
|
|
158
|
-
* @param {string} mint - Token address 代币地址
|
|
154
|
+
* @param {string} mint - Token address
|
|
159
155
|
* @param {bigint|string|number} buySolAmount - SOL amount to spend (u64 format, lamports)
|
|
160
156
|
* @returns {Promise<Object>} Buy simulation result with the following structure:
|
|
161
157
|
* - success: {boolean} Whether the simulation was successful
|
|
@@ -272,8 +268,7 @@ class SimulatorModule {
|
|
|
272
268
|
|
|
273
269
|
/**
|
|
274
270
|
* Simulate sell transaction with token amount input
|
|
275
|
-
*
|
|
276
|
-
* @param {string} mint - Token address 代币地址
|
|
271
|
+
* @param {string} mint - Token address
|
|
277
272
|
* @param {bigint|string|number} sellTokenAmount - Token amount to sell (u64 format, lamports)
|
|
278
273
|
* @returns {Promise<Object>} Sell simulation result with the following structure:
|
|
279
274
|
* - success: {boolean} Whether the simulation was successful
|