pinpet-sdk 2.1.23 → 2.1.25

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.
@@ -41917,12 +41917,12 @@ decimal.exports;
41917
41917
 
41918
41918
  var decimalExports = decimal.exports;
41919
41919
 
41920
- const Decimal$1 = decimalExports;
41920
+ const Decimal$2 = decimalExports;
41921
41921
 
41922
41922
  // Configure Decimal.js to use 50-bit precision for better accuracy with tiny prices
41923
41923
  // Increased from 28 to 50 to handle extremely small prices (e.g., 0.000000041571)
41924
41924
  // ROUND_HALF_UP ensures consistent rounding behavior
41925
- Decimal$1.set({ precision: 50, rounding: Decimal$1.ROUND_HALF_UP });
41925
+ Decimal$2.set({ precision: 50, rounding: Decimal$2.ROUND_HALF_UP });
41926
41926
 
41927
41927
 
41928
41928
  /**
@@ -41950,19 +41950,19 @@ class CurveAMM$8 {
41950
41950
  * Initial SOL reserve amount, represented as Decimal
41951
41951
  * @type {Decimal}
41952
41952
  */
41953
- static INITIAL_SOL_RESERVE_DECIMAL = new Decimal$1('30');
41953
+ static INITIAL_SOL_RESERVE_DECIMAL = new Decimal$2('30');
41954
41954
 
41955
41955
  /**
41956
41956
  * Initial Token reserve amount, represented as Decimal
41957
41957
  * @type {Decimal}
41958
41958
  */
41959
- static INITIAL_TOKEN_RESERVE_DECIMAL = new Decimal$1('1073000000');
41959
+ static INITIAL_TOKEN_RESERVE_DECIMAL = new Decimal$2('1073000000');
41960
41960
 
41961
41961
  /**
41962
41962
  * Initial constant K value, represented as Decimal
41963
41963
  * @type {Decimal}
41964
41964
  */
41965
- static INITIAL_K_DECIMAL = new Decimal$1('32190000000');
41965
+ static INITIAL_K_DECIMAL = new Decimal$2('32190000000');
41966
41966
 
41967
41967
  /**
41968
41968
  * Minimum price that can appear, below this price may cause overflow
@@ -41970,26 +41970,26 @@ class CurveAMM$8 {
41970
41970
  * Reduced from 1e-9 to 1e-12 to support wider range of pool configurations
41971
41971
  * @type {Decimal}
41972
41972
  */
41973
- static INITIAL_MIN_PRICE_DECIMAL = new Decimal$1('0.000000000001'); // 1e-12
41973
+ static INITIAL_MIN_PRICE_DECIMAL = new Decimal$2('0.000000000001'); // 1e-12
41974
41974
 
41975
41975
  /**
41976
41976
  * Decimal representation of precision factor = 10^23
41977
41977
  * @type {Decimal}
41978
41978
  */
41979
41979
  //static PRICE_PRECISION_FACTOR_DECIMAL = new Decimal('10000000000000000000000000000');
41980
- static PRICE_PRECISION_FACTOR_DECIMAL = new Decimal$1('100000000000000000000000');
41980
+ static PRICE_PRECISION_FACTOR_DECIMAL = new Decimal$2('100000000000000000000000');
41981
41981
 
41982
41982
  /**
41983
41983
  * Decimal representation of Token precision factor = 1000000000 (10^9)
41984
41984
  * @type {Decimal}
41985
41985
  */
41986
- static TOKEN_PRECISION_FACTOR_DECIMAL = new Decimal$1('1000000000');
41986
+ static TOKEN_PRECISION_FACTOR_DECIMAL = new Decimal$2('1000000000');
41987
41987
 
41988
41988
  /**
41989
41989
  * Decimal representation of SOL precision factor = 1000000000
41990
41990
  * @type {Decimal}
41991
41991
  */
41992
- static SOL_PRECISION_FACTOR_DECIMAL = new Decimal$1('1000000000');
41992
+ static SOL_PRECISION_FACTOR_DECIMAL = new Decimal$2('1000000000');
41993
41993
 
41994
41994
 
41995
41995
  /**
@@ -42018,7 +42018,7 @@ class CurveAMM$8 {
42018
42018
  if (typeof price === 'bigint') {
42019
42019
  price = price.toString();
42020
42020
  }
42021
- const priceDecimal = new Decimal$1(price);
42021
+ const priceDecimal = new Decimal$2(price);
42022
42022
  return priceDecimal.div(this.PRICE_PRECISION_FACTOR_DECIMAL);
42023
42023
  }
42024
42024
 
@@ -42068,9 +42068,9 @@ class CurveAMM$8 {
42068
42068
  if (typeof price === 'bigint') {
42069
42069
  price = price.toString();
42070
42070
  }
42071
- const priceDecimal = new Decimal$1(price);
42071
+ const priceDecimal = new Decimal$2(price);
42072
42072
  // Use old precision factor 10^15
42073
- const oldPrecisionFactor = new Decimal$1('1000000000000000');
42073
+ const oldPrecisionFactor = new Decimal$2('1000000000000000');
42074
42074
  return priceDecimal.div(oldPrecisionFactor);
42075
42075
  }
42076
42076
 
@@ -42083,7 +42083,7 @@ class CurveAMM$8 {
42083
42083
  */
42084
42084
  static decimalToU64(price) {
42085
42085
  // Directly use old precision factor for conversion
42086
- const oldPrecisionFactor = new Decimal$1('1000000000000000');
42086
+ const oldPrecisionFactor = new Decimal$2('1000000000000000');
42087
42087
  const scaled = price.mul(oldPrecisionFactor);
42088
42088
  const floored = scaled.floor();
42089
42089
  if (floored.isNaN() || floored.isNegative() || floored.gt('18446744073709551615')) {
@@ -42102,7 +42102,7 @@ class CurveAMM$8 {
42102
42102
  */
42103
42103
  static decimalToU64Ceil(price) {
42104
42104
  // Directly use old precision factor for conversion
42105
- const oldPrecisionFactor = new Decimal$1('1000000000000000');
42105
+ const oldPrecisionFactor = new Decimal$2('1000000000000000');
42106
42106
  const scaled = price.mul(oldPrecisionFactor);
42107
42107
  const ceiled = scaled.ceil();
42108
42108
  if (ceiled.isNaN() || ceiled.isNegative() || ceiled.gt('18446744073709551615')) {
@@ -42186,7 +42186,7 @@ class CurveAMM$8 {
42186
42186
  if (typeof amount === 'bigint') {
42187
42187
  amount = amount.toString();
42188
42188
  }
42189
- const amountDecimal = new Decimal$1(amount);
42189
+ const amountDecimal = new Decimal$2(amount);
42190
42190
  return amountDecimal.div(this.TOKEN_PRECISION_FACTOR_DECIMAL);
42191
42191
  }
42192
42192
 
@@ -42200,7 +42200,7 @@ class CurveAMM$8 {
42200
42200
  if (typeof amount === 'bigint') {
42201
42201
  amount = amount.toString();
42202
42202
  }
42203
- const amountDecimal = new Decimal$1(amount);
42203
+ const amountDecimal = new Decimal$2(amount);
42204
42204
  return amountDecimal.div(this.SOL_PRECISION_FACTOR_DECIMAL);
42205
42205
  }
42206
42206
 
@@ -42218,8 +42218,8 @@ class CurveAMM$8 {
42218
42218
  * const k2 = CurveAMM.calculateK(60, 1073000000);
42219
42219
  */
42220
42220
  static calculateK(initialVirtualSol, initialVirtualToken) {
42221
- const sol = new Decimal$1(initialVirtualSol);
42222
- const token = new Decimal$1(initialVirtualToken);
42221
+ const sol = new Decimal$2(initialVirtualSol);
42222
+ const token = new Decimal$2(initialVirtualToken);
42223
42223
  return sol.mul(token);
42224
42224
  }
42225
42225
 
@@ -42241,8 +42241,8 @@ class CurveAMM$8 {
42241
42241
  * @returns {bigint|null} u128格式的初始价格
42242
42242
  */
42243
42243
  static getInitialPriceWithParams(initialVirtualSol, initialVirtualToken) {
42244
- const sol = new Decimal$1(initialVirtualSol);
42245
- const token = new Decimal$1(initialVirtualToken);
42244
+ const sol = new Decimal$2(initialVirtualSol);
42245
+ const token = new Decimal$2(initialVirtualToken);
42246
42246
  const initialPrice = sol.div(token);
42247
42247
  return this.decimalToU128(initialPrice);
42248
42248
  }
@@ -42485,7 +42485,7 @@ class CurveAMM$8 {
42485
42485
  }
42486
42486
 
42487
42487
  // Warning for extremely small prices that may have precision issues
42488
- const warningPrice = new Decimal$1('0.0000001'); // 10^-7
42488
+ const warningPrice = new Decimal$2('0.0000001'); // 10^-7
42489
42489
  if (price.lt(warningPrice)) {
42490
42490
  // Only log once per execution to avoid spam (use a static flag)
42491
42491
  if (!this._tinyPriceWarningShown) {
@@ -43028,6 +43028,36 @@ class CurveAMM$8 {
43028
43028
  }
43029
43029
  }
43030
43030
 
43031
+ /**
43032
+ * Calculate total amount including fee (with ceiling division, matching Rust contract)
43033
+ *
43034
+ * @param {bigint|string|number} solAmount - Net amount (base amount)
43035
+ * @param {number} fee - Fee rate, expressed with FEE_DENOMINATOR as denominator
43036
+ * Example: 1000 represents 1% fee (1000/100000)
43037
+ * 2000 represents 2% fee (2000/100000)
43038
+ * @returns {bigint|null} Returns total amount including fee on success, null on failure
43039
+ * Total amount calculation uses ceiling division (rounding up), matching Rust contract behavior
43040
+ */
43041
+ static calculateTotalAmountWithFee(solAmount, fee) {
43042
+ try {
43043
+ const amount = BigInt(solAmount.toString());
43044
+ const feeBig = BigInt(fee);
43045
+
43046
+ // Check if fee rate is valid (must be less than or equal to 10%)
43047
+ if (feeBig > MAX_FEE_RATE) {
43048
+ return null;
43049
+ }
43050
+
43051
+ // Ceiling division: (amount * (FEE_DENOMINATOR + fee) + FEE_DENOMINATOR - 1) / FEE_DENOMINATOR
43052
+ const numerator = amount * (FEE_DENOMINATOR + feeBig);
43053
+ const totalAmount = (numerator + FEE_DENOMINATOR - 1n) / FEE_DENOMINATOR;
43054
+
43055
+ return totalAmount;
43056
+ } catch (error) {
43057
+ return null;
43058
+ }
43059
+ }
43060
+
43031
43061
  /**
43032
43062
  * Convert u128 price to readable decimal string format for display
43033
43063
  *
@@ -43039,7 +43069,7 @@ class CurveAMM$8 {
43039
43069
  if (typeof price === 'bigint') {
43040
43070
  price = price.toString();
43041
43071
  }
43042
- const priceDecimal = new Decimal$1(price);
43072
+ const priceDecimal = new Decimal$2(price);
43043
43073
  const convertedPrice = priceDecimal.div(this.PRICE_PRECISION_FACTOR_DECIMAL);
43044
43074
  return convertedPrice.toFixed(decimalPlaces);
43045
43075
  }
@@ -45058,6 +45088,7 @@ jsonBigint.exports.stringify = json_stringify;
45058
45088
 
45059
45089
  var jsonBigintExports = jsonBigint.exports;
45060
45090
 
45091
+ const Decimal$1 = decimalExports;
45061
45092
  const CurveAMM$6 = curve_amm;
45062
45093
  const {transformOrdersData , checkPriceRangeOverlap} = stop_loss_utils;
45063
45094
  const { PRICE_ADJUSTMENT_PERCENTAGE, MIN_STOP_LOSS_PERCENT } = utils$2;
@@ -45183,13 +45214,23 @@ jsonBigintExports({ storeAsString: false });
45183
45214
  * @since 2.0.0
45184
45215
  * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
45185
45216
  */
45186
- async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
45217
+ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
45187
45218
  try {
45188
45219
  // Parameter validation
45189
45220
  if (!mint || !buyTokenAmount || !stopLossPrice) {
45190
45221
  throw new Error('Missing required parameters');
45191
45222
  }
45192
45223
 
45224
+ // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
45225
+ if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
45226
+ const curveAccount = await this.sdk.chain.getCurveAccount(mint);
45227
+ if (borrowFee === null) borrowFee = curveAccount.borrowFee;
45228
+ // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
45229
+ // 与 calcLiq.js 中的转换方式一致
45230
+ if (initialVirtualSol === null) initialVirtualSol = new Decimal$1(curveAccount.initialVirtualSol.toString()).div(CurveAMM$6.SOL_PRECISION_FACTOR_DECIMAL).toString();
45231
+ if (initialVirtualToken === null) initialVirtualToken = new Decimal$1(curveAccount.initialVirtualToken.toString()).div(CurveAMM$6.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
45232
+ }
45233
+
45193
45234
  // Get current price
45194
45235
  if (!lastPrice) {
45195
45236
  //console.log('Getting current price...');
@@ -45198,7 +45239,7 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45198
45239
  throw new Error('Failed to get current price');
45199
45240
  }
45200
45241
  }
45201
- console.log("simulateLongStopLoss lastPrice=",lastPrice);
45242
+ //console.log("simulateLongStopLoss lastPrice=",lastPrice)
45202
45243
 
45203
45244
  // Get ordersData
45204
45245
  if (!ordersData) {
@@ -45210,17 +45251,17 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45210
45251
  }
45211
45252
 
45212
45253
  //console.log("ordersData=", JSONbig.stringify(ordersData, null, 2))
45213
- console.log("ordersData len=", ordersData.data.orders.length);
45254
+ //console.log("ordersData len=", ordersData.data.orders.length)
45214
45255
 
45215
45256
  // Calculate current price
45216
45257
  let currentPrice;
45217
45258
  if (lastPrice === null || lastPrice === undefined || lastPrice === '0') {
45218
- console.log('Current price is empty, using initial price');
45259
+ //console.log('Current price is empty, using initial price');
45219
45260
  currentPrice = CurveAMM$6.getInitialPrice();
45220
45261
  } else {
45221
45262
  currentPrice = BigInt(lastPrice);
45222
45263
  if (!currentPrice || currentPrice === 0n) {
45223
- console.log('Current price is 0, using initial price');
45264
+ //console.log('Current price is 0, using initial price');
45224
45265
  currentPrice = CurveAMM$6.getInitialPrice();
45225
45266
  }
45226
45267
  }
@@ -45228,7 +45269,7 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45228
45269
 
45229
45270
  // Transform orders data
45230
45271
  const downOrders = transformOrdersData(ordersData);
45231
- console.log(`downOrders Found ${downOrders.length} existing long orders`);
45272
+ //console.log(`downOrders Found ${downOrders.length} existing long orders`);
45232
45273
  //console.log("downOrders downOrders=",downOrders)
45233
45274
 
45234
45275
  // Initialize stop loss prices
@@ -45266,7 +45307,7 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45266
45307
  // console.log(` - buyTokenAmount: ${buyTokenAmount.toString()}`);
45267
45308
  // console.log(` - Calling CurveAMM.sellFromPriceWithTokenInput...`);
45268
45309
 
45269
- const tradeResult = CurveAMM$6.sellFromPriceWithTokenInput(stopLossStartPrice, buyTokenAmount);
45310
+ const tradeResult = CurveAMM$6.sellFromPriceWithTokenInputWithParams(stopLossStartPrice, buyTokenAmount, initialVirtualSol, initialVirtualToken);
45270
45311
 
45271
45312
  //console.log(` - tradeResult:`, tradeResult);
45272
45313
 
@@ -45330,10 +45371,10 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45330
45371
  let estimatedMargin = 0n;
45331
45372
  try {
45332
45373
  // 1. 计算从当前价格买入所需的SOL
45333
- const buyResult = CurveAMM$6.buyFromPriceWithTokenOutput(currentPrice, buyTokenAmount);
45374
+ const buyResult = CurveAMM$6.buyFromPriceWithTokenOutputWithParams(currentPrice, buyTokenAmount, initialVirtualSol, initialVirtualToken);
45334
45375
  if (buyResult) {
45335
45376
  const requiredSol = buyResult[1]; // SOL input amount
45336
-
45377
+
45337
45378
  // 2. 计算平仓时扣除手续费后的收益
45338
45379
  const closeOutputSolAfterFee = CurveAMM$6.calculateAmountAfterFee(finalTradeAmount, borrowFee);
45339
45380
 
@@ -45493,13 +45534,23 @@ async function simulateLongStopLoss$1(mint, buyTokenAmount, stopLossPrice, lastP
45493
45534
  * @since 2.0.0
45494
45535
  * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
45495
45536
  */
45496
- async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
45537
+ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
45497
45538
  try {
45498
45539
  // Parameter validation
45499
45540
  if (!mint || !sellTokenAmount || !stopLossPrice) {
45500
45541
  throw new Error('Missing required parameters');
45501
45542
  }
45502
45543
 
45544
+ // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
45545
+ if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
45546
+ const curveAccount = await this.sdk.chain.getCurveAccount(mint);
45547
+ if (borrowFee === null) borrowFee = curveAccount.borrowFee;
45548
+ // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
45549
+ // 与 calcLiq.js 中的转换方式一致
45550
+ if (initialVirtualSol === null) initialVirtualSol = new Decimal$1(curveAccount.initialVirtualSol.toString()).div(CurveAMM$6.SOL_PRECISION_FACTOR_DECIMAL).toString();
45551
+ if (initialVirtualToken === null) initialVirtualToken = new Decimal$1(curveAccount.initialVirtualToken.toString()).div(CurveAMM$6.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
45552
+ }
45553
+
45503
45554
  // Get current price
45504
45555
  if (!lastPrice) {
45505
45556
  //console.log('Getting current price...');
@@ -45519,24 +45570,24 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45519
45570
  }
45520
45571
 
45521
45572
  //console.log("ordersData=", JSONbig.stringify(ordersData, null, 2))
45522
- console.log("ordersData len=", ordersData.data.orders.length);
45573
+ //console.log("ordersData len=", ordersData.data.orders.length)
45523
45574
 
45524
45575
  // Calculate current price
45525
45576
  let currentPrice;
45526
45577
  if (lastPrice === null || lastPrice === undefined || lastPrice === '0') {
45527
- console.log('Current price is empty, using initial price');
45578
+ //console.log('Current price is empty, using initial price');
45528
45579
  currentPrice = CurveAMM$6.getInitialPrice();
45529
45580
  } else {
45530
45581
  currentPrice = BigInt(lastPrice);
45531
45582
  if (!currentPrice || currentPrice === 0n) {
45532
- console.log('Current price is 0, using initial price');
45583
+ //console.log('Current price is 0, using initial price');
45533
45584
  currentPrice = CurveAMM$6.getInitialPrice();
45534
45585
  }
45535
45586
  }
45536
45587
 
45537
45588
  // Transform orders data
45538
45589
  const upOrders = transformOrdersData(ordersData);
45539
- console.log(`upOrders Found ${upOrders.length} existing short orders`);
45590
+ //console.log(`upOrders Found ${upOrders.length} existing short orders`);
45540
45591
 
45541
45592
  // Initialize stop loss prices
45542
45593
  let stopLossStartPrice = BigInt(stopLossPrice);
@@ -45554,11 +45605,7 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45554
45605
  stopLossStartPrice = minAllowedStopLoss;
45555
45606
  const originalPercent = Number((originalStopLoss - currentPrice) * 1000n / currentPrice) / 10;
45556
45607
  const adjustedPercent = Number((stopLossStartPrice - currentPrice) * 1000n / currentPrice) / 10;
45557
- console.log(`止损价格自动调整以满足最小距离要求:`);
45558
- console.log(` 原始止损距离: ${originalPercent.toFixed(2)}%`);
45559
- console.log(` 调整后距离: ${adjustedPercent.toFixed(2)}% (最小要求: ${Number(MIN_STOP_LOSS_PERCENT) / 10}%)`);
45560
- console.log(` 原始止损价: ${originalStopLoss}`);
45561
- console.log(` 调整后止损价: ${stopLossStartPrice}`);
45608
+
45562
45609
  }
45563
45610
 
45564
45611
  //console.log(`Start price: ${stopLossStartPrice}, Target token amount: ${sellTokenAmount}`);
@@ -45573,7 +45620,7 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45573
45620
  // console.log(` - sellTokenAmount: ${sellTokenAmount.toString()}`);
45574
45621
  // console.log(` - Calling CurveAMM.buyFromPriceWithTokenOutput...`);
45575
45622
 
45576
- const tradeResult = CurveAMM$6.buyFromPriceWithTokenOutput(stopLossStartPrice, sellTokenAmount);
45623
+ const tradeResult = CurveAMM$6.buyFromPriceWithTokenOutputWithParams(stopLossStartPrice, sellTokenAmount, initialVirtualSol, initialVirtualToken);
45577
45624
 
45578
45625
  //console.log(` - tradeResult:`, tradeResult);
45579
45626
 
@@ -45633,23 +45680,24 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45633
45680
  const leverage = Number((BigInt(10000) * currentPrice) / (executableStopLossPrice - currentPrice)) / 10000;
45634
45681
 
45635
45682
  // 计算保证金 / Calculate margin requirement
45683
+ // 与合约公式一致 (long_short.rs 第890-894行):
45684
+ // real_margin_sol = close_buy_sol_with_fee - output_sol - fee_sol
45685
+ // 其中 output_sol 是扣费后净SOL, fee_sol 是开仓手续费
45686
+ // 展开: real_margin_sol = close_buy_sol_with_fee - raw_sell_sol
45636
45687
  let estimatedMargin = 0n;
45688
+ let rawSellSol = 0n; // 卖出 token 获得的原始 SOL(未扣费),供调用方计算 minSolOutput
45637
45689
  try {
45638
- // 1. 计算从当前价格卖出代币获得的SOL(开仓收益,不含手续费)
45639
- const sellResult = CurveAMM$6.sellFromPriceWithTokenInput(currentPrice, sellTokenAmount);
45690
+ // 1. 计算从当前价格卖出代币获得的原始SOL(未扣费)
45691
+ const sellResult = CurveAMM$6.sellFromPriceWithTokenInputWithParams(currentPrice, sellTokenAmount, initialVirtualSol, initialVirtualToken);
45640
45692
  if (sellResult) {
45641
- const openingSolGain = sellResult[1]; // 卖出获得的SOL
45642
-
45643
- // 2. 计算开仓手续费
45644
- const openingFee = (openingSolGain * BigInt(borrowFee)) / 100000n;
45645
-
45646
- // 3. 计算平仓成本(含手续费)
45647
- const feeAmount = (finalTradeAmount * BigInt(borrowFee)) / 100000n;
45648
- const closeCostWithFee = finalTradeAmount + feeAmount;
45649
-
45650
- // 4. 计算保证金 = 平仓成本(含手续费) - 开仓收益 - 开仓手续费
45651
- if (closeCostWithFee > openingSolGain + openingFee) {
45652
- estimatedMargin = closeCostWithFee - openingSolGain - openingFee;
45693
+ rawSellSol = sellResult[1]; // 卖出获得的原始SOL(未扣费)
45694
+
45695
+ // 2. 计算平仓成本(含手续费,使用 ceiling 除法与合约一致)
45696
+ const closeCostWithFee = CurveAMM$6.calculateTotalAmountWithFee(finalTradeAmount, borrowFee);
45697
+
45698
+ // 3. 保证金 = 平仓成本(含费) - 原始卖出SOL
45699
+ if (closeCostWithFee !== null && closeCostWithFee > rawSellSol) {
45700
+ estimatedMargin = closeCostWithFee - rawSellSol;
45653
45701
  }
45654
45702
  }
45655
45703
  } catch (marginError) {
@@ -45666,14 +45714,15 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45666
45714
 
45667
45715
  return {
45668
45716
  executableStopLossPrice: executableStopLossPrice, // Calculated reasonable stop loss value
45669
- tradeAmount: finalTradeAmount, // SOL input amount
45717
+ tradeAmount: finalTradeAmount, // SOL input amount (平仓时买回 token 需要的 SOL)
45670
45718
  stopLossPercentage: stopLossPercentage, // Stop loss percentage relative to current price
45671
45719
  leverage: leverage, // Leverage ratio
45672
45720
  currentPrice: currentPrice, // Current price
45673
45721
  iterations: iteration, // Number of adjustments
45674
45722
  originalStopLossPrice: BigInt(stopLossPrice), // Original stop loss price
45675
45723
  close_insert_indices: finalOverlapResult.close_insert_indices, // Candidate insertion indices for closing order
45676
- estimatedMargin: estimatedMargin // Estimated margin requirement in SOL (lamports)
45724
+ estimatedMargin: estimatedMargin, // Estimated margin requirement in SOL (lamports)
45725
+ rawSellSol: rawSellSol // 卖出 token 获得的原始 SOL(未扣费),用于调用方计算 minSolOutput
45677
45726
  };
45678
45727
 
45679
45728
  } catch (error) {
@@ -45742,13 +45791,23 @@ async function simulateShortStopLoss$1(mint, sellTokenAmount, stopLossPrice, las
45742
45791
  * @since 2.0.0
45743
45792
  * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
45744
45793
  */
45745
- async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
45794
+ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
45746
45795
  try {
45747
45796
  // Parameter validation
45748
45797
  if (!mint || !buySolAmount || !stopLossPrice) {
45749
45798
  throw new Error('Missing required parameters');
45750
45799
  }
45751
45800
 
45801
+ // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
45802
+ if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
45803
+ const curveAccount = await this.sdk.chain.getCurveAccount(mint);
45804
+ if (borrowFee === null) borrowFee = curveAccount.borrowFee;
45805
+ // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
45806
+ // 与 calcLiq.js 中的转换方式一致
45807
+ if (initialVirtualSol === null) initialVirtualSol = new Decimal$1(curveAccount.initialVirtualSol.toString()).div(CurveAMM$6.SOL_PRECISION_FACTOR_DECIMAL).toString();
45808
+ if (initialVirtualToken === null) initialVirtualToken = new Decimal$1(curveAccount.initialVirtualToken.toString()).div(CurveAMM$6.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
45809
+ }
45810
+
45752
45811
  // Get current price if not provided
45753
45812
  let currentPrice;
45754
45813
  if (!lastPrice) {
@@ -45770,7 +45829,7 @@ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, last
45770
45829
 
45771
45830
  // Calculate initial token amount from SOL amount using sellFromPriceWithSolOutput
45772
45831
  // This gives us how many tokens we can get when we later sell for buySolAmount SOL
45773
- const initialResult = CurveAMM$6.sellFromPriceWithSolOutput(currentPrice, buySolAmount);
45832
+ const initialResult = CurveAMM$6.sellFromPriceWithSolOutputWithParams(currentPrice, buySolAmount, initialVirtualSol, initialVirtualToken);
45774
45833
  if (!initialResult) {
45775
45834
  throw new Error('Failed to calculate token amount from SOL amount');
45776
45835
  }
@@ -45778,12 +45837,21 @@ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, last
45778
45837
  let buyTokenAmount = initialResult[1]; // Token amount
45779
45838
  let stopLossResult;
45780
45839
  let iterations = 0;
45781
- const maxIterations = 15;
45840
+ const maxIterations = 50;
45841
+
45842
+ // 根据杠杆倍数动态计算二分查找上界
45843
+ // 高杠杆(如20x)时止损距离小,每个代币的保证金贡献小,需要更多代币才能消耗完保证金
45844
+ // Calculate dynamic binary search upper bound based on leverage
45845
+ const stopLossPriceBigInt = BigInt(stopLossPrice);
45846
+ const priceDiff = currentPrice - stopLossPriceBigInt;
45847
+ const estimatedLeverage = priceDiff > 0n ? Number(currentPrice * 10000n / priceDiff) / 10000 : 10;
45848
+ const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3倍安全系数
45849
+ const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // 最小10倍
45782
45850
 
45783
45851
  // 使用二分查找算法找到 estimatedMargin < buySolAmount 的最大值
45784
45852
  // Use binary search algorithm to find maximum estimatedMargin that is less than buySolAmount
45785
45853
  let left = 1n; // 最小值,确保有一个有效的下界
45786
- let right = buyTokenAmount * 10n; // 上界:初始值的10倍
45854
+ let right = buyTokenAmount * multiplier; // 上界:根据杠杆动态计算
45787
45855
  let bestResult = null;
45788
45856
  let bestMargin = 0n; // 记录最大的合法 estimatedMargin
45789
45857
  let bestTokenAmount = buyTokenAmount;
@@ -45793,7 +45861,7 @@ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, last
45793
45861
  const mid = (left + right) / 2n;
45794
45862
 
45795
45863
  // 计算当前 token 数量的结果
45796
- const currentResult = await simulateLongStopLoss$1.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee);
45864
+ const currentResult = await simulateLongStopLoss$1.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
45797
45865
  const currentMargin = currentResult.estimatedMargin;
45798
45866
 
45799
45867
  //console.log(`Binary search iteration ${iterations}: tokenAmount=${mid}, estimatedMargin=${currentMargin}, target=${buySolAmount}`);
@@ -45835,7 +45903,7 @@ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, last
45835
45903
  //console.log(`No valid solution found (estimatedMargin < buySolAmount), using minimal tokenAmount`);
45836
45904
  buyTokenAmount = buyTokenAmount / 10n; // 使用更小的值
45837
45905
  if (buyTokenAmount <= 0n) buyTokenAmount = 1000000000n; // 最小值保护 (0.001 token with 9 decimals)
45838
- stopLossResult = await simulateLongStopLoss$1.call(this, mint, buyTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
45906
+ stopLossResult = await simulateLongStopLoss$1.call(this, mint, buyTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
45839
45907
  }
45840
45908
 
45841
45909
  // if (iterations >= maxIterations) {
@@ -45907,13 +45975,23 @@ async function simulateLongSolStopLoss$1(mint, buySolAmount, stopLossPrice, last
45907
45975
  * @since 2.0.0
45908
45976
  * @version 2.0.0 - 从返回 prev_order_pda/next_order_pda 改为返回 close_insert_indices
45909
45977
  */
45910
- async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
45978
+ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null, initialVirtualSol = null, initialVirtualToken = null) {
45911
45979
  try {
45912
45980
  // Parameter validation
45913
45981
  if (!mint || !sellSolAmount || !stopLossPrice) {
45914
45982
  throw new Error('Missing required parameters');
45915
45983
  }
45916
45984
 
45985
+ // 如果没有传入 borrowFee 或池子参数,从链上一次性获取
45986
+ if (borrowFee === null || initialVirtualSol === null || initialVirtualToken === null) {
45987
+ const curveAccount = await this.sdk.chain.getCurveAccount(mint);
45988
+ if (borrowFee === null) borrowFee = curveAccount.borrowFee;
45989
+ // 链上返回的是 u64 原始单位(lamports/最小单位),需要除以 10^9 转为人类可读单位
45990
+ // 与 calcLiq.js 中的转换方式一致
45991
+ if (initialVirtualSol === null) initialVirtualSol = new Decimal$1(curveAccount.initialVirtualSol.toString()).div(CurveAMM$6.SOL_PRECISION_FACTOR_DECIMAL).toString();
45992
+ if (initialVirtualToken === null) initialVirtualToken = new Decimal$1(curveAccount.initialVirtualToken.toString()).div(CurveAMM$6.TOKEN_PRECISION_FACTOR_DECIMAL).toString();
45993
+ }
45994
+
45917
45995
  // Get current price if not provided
45918
45996
  let currentPrice;
45919
45997
  if (!lastPrice) {
@@ -45923,7 +46001,7 @@ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, la
45923
46001
  }
45924
46002
  }
45925
46003
 
45926
- console.log("simulateShortSolStopLoss lastPrice=",lastPrice);
46004
+ //console.log("simulateShortSolStopLoss lastPrice=",lastPrice)
45927
46005
 
45928
46006
  // Calculate current price
45929
46007
  if (lastPrice === null || lastPrice === undefined || lastPrice === '0') {
@@ -45937,7 +46015,7 @@ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, la
45937
46015
 
45938
46016
  // Calculate initial token amount from SOL amount using buyFromPriceWithSolInput
45939
46017
  // This gives us how many tokens we need to buy later using sellSolAmount SOL
45940
- const initialResult = CurveAMM$6.buyFromPriceWithSolInput(currentPrice, sellSolAmount);
46018
+ const initialResult = CurveAMM$6.buyFromPriceWithSolInputWithParams(currentPrice, sellSolAmount, initialVirtualSol, initialVirtualToken);
45941
46019
  if (!initialResult) {
45942
46020
  throw new Error('Failed to calculate token amount from SOL amount');
45943
46021
  }
@@ -45945,12 +46023,21 @@ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, la
45945
46023
  let sellTokenAmount = initialResult[1]; // Token amount
45946
46024
  let stopLossResult;
45947
46025
  let iterations = 0;
45948
- const maxIterations = 15;
46026
+ const maxIterations = 50;
46027
+
46028
+ // 根据杠杆倍数动态计算二分查找上界
46029
+ // 高杠杆(如20x)时止损距离小,每个代币的保证金贡献小,需要更多代币才能消耗完保证金
46030
+ // Calculate dynamic binary search upper bound based on leverage
46031
+ const stopLossPriceBigInt = BigInt(stopLossPrice);
46032
+ const priceDiff = stopLossPriceBigInt - currentPrice;
46033
+ const estimatedLeverage = priceDiff > 0n ? Number(currentPrice * 10000n / priceDiff) / 10000 : 10;
46034
+ const safeMultiplier = BigInt(Math.ceil(estimatedLeverage * 3)); // 3倍安全系数
46035
+ const multiplier = safeMultiplier > 10n ? safeMultiplier : 10n; // 最小10倍
45949
46036
 
45950
46037
  // 使用二分查找算法找到 estimatedMargin < sellSolAmount 的最大值
45951
46038
  // Use binary search algorithm to find maximum estimatedMargin that is less than sellSolAmount
45952
46039
  let left = 1n; // 最小值,确保有一个有效的下界
45953
- let right = sellTokenAmount * 10n; // 上界:初始值的10倍
46040
+ let right = sellTokenAmount * multiplier; // 上界:根据杠杆动态计算
45954
46041
  let bestResult = null;
45955
46042
  let bestMargin = 0n; // 记录最大的合法 estimatedMargin
45956
46043
  let bestTokenAmount = sellTokenAmount;
@@ -45960,7 +46047,7 @@ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, la
45960
46047
  const mid = (left + right) / 2n;
45961
46048
 
45962
46049
  // 计算当前 token 数量的结果
45963
- const currentResult = await simulateShortStopLoss$1.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee);
46050
+ const currentResult = await simulateShortStopLoss$1.call(this, mint, mid, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
45964
46051
  const currentMargin = currentResult.estimatedMargin;
45965
46052
 
45966
46053
  //console.log(`Binary search iteration ${iterations}: tokenAmount=${mid}, estimatedMargin=${currentMargin}, target=${sellSolAmount}`);
@@ -46002,7 +46089,7 @@ async function simulateShortSolStopLoss$1(mint, sellSolAmount, stopLossPrice, la
46002
46089
  //console.log(`No valid solution found (estimatedMargin < sellSolAmount), using minimal tokenAmount`);
46003
46090
  sellTokenAmount = sellTokenAmount / 10n; // 使用更小的值
46004
46091
  if (sellTokenAmount <= 0n) sellTokenAmount = 1000000000n; // 最小值保护 (0.001 token with 9 decimals)
46005
- stopLossResult = await simulateShortStopLoss$1.call(this, mint, sellTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
46092
+ stopLossResult = await simulateShortStopLoss$1.call(this, mint, sellTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee, initialVirtualSol, initialVirtualToken);
46006
46093
  }
46007
46094
 
46008
46095
  // if (iterations >= maxIterations) {
@@ -47696,8 +47783,8 @@ class SimulatorModule$1 {
47696
47783
  * @param {Object|null} ordersData - Orders data, default null
47697
47784
  * @returns {Promise<Object>} Stop loss analysis result
47698
47785
  */
47699
- async simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPrice = null, ordersData = null) {
47700
- return simulateLongStopLoss.call(this, mint, buyTokenAmount, stopLossPrice, lastPrice, ordersData);
47786
+ async simulateLongStopLoss(mint, buyTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null) {
47787
+ return simulateLongStopLoss.call(this, mint, buyTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
47701
47788
  }
47702
47789
 
47703
47790
  /**
@@ -47709,8 +47796,8 @@ class SimulatorModule$1 {
47709
47796
  * @param {Object|null} ordersData - Orders data, default null
47710
47797
  * @returns {Promise<Object>} Stop loss analysis result
47711
47798
  */
47712
- async simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastPrice = null, ordersData = null) {
47713
- return simulateShortStopLoss.call(this, mint, sellTokenAmount, stopLossPrice, lastPrice, ordersData);
47799
+ async simulateShortStopLoss(mint, sellTokenAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null) {
47800
+ return simulateShortStopLoss.call(this, mint, sellTokenAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
47714
47801
  }
47715
47802
 
47716
47803
  /**
@@ -47723,7 +47810,7 @@ class SimulatorModule$1 {
47723
47810
  * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
47724
47811
  * @returns {Promise<Object>} Stop loss analysis result (same as simulateLongStopLoss)
47725
47812
  */
47726
- async simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
47813
+ async simulateLongSolStopLoss(mint, buySolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null) {
47727
47814
  return simulateLongSolStopLoss.call(this, mint, buySolAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
47728
47815
  }
47729
47816
 
@@ -47737,7 +47824,7 @@ class SimulatorModule$1 {
47737
47824
  * @param {number} borrowFee - Borrow fee rate, default 2000 (2000/100000 = 0.02%)
47738
47825
  * @returns {Promise<Object>} Stop loss analysis result (same as simulateShortStopLoss)
47739
47826
  */
47740
- async simulateShortSolStopLoss(mint, sellSolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = 2000) {
47827
+ async simulateShortSolStopLoss(mint, sellSolAmount, stopLossPrice, lastPrice = null, ordersData = null, borrowFee = null) {
47741
47828
  return simulateShortSolStopLoss.call(this, mint, sellSolAmount, stopLossPrice, lastPrice, ordersData, borrowFee);
47742
47829
  }
47743
47830
 
@@ -49673,7 +49760,7 @@ class OrderUtils$2 {
49673
49760
 
49674
49761
  var orderUtils = OrderUtils$2;
49675
49762
 
49676
- var address = "CYdRzRacZ5kTc9Ht3U7mFhbsyxG3sZGEzC4cNf2Gjg2W";
49763
+ var address = "F2FzigE1Z374iDvreiM6hZQe6oGXgomJfv8PyybvUXye";
49677
49764
  var metadata = {
49678
49765
  name: "pinpet",
49679
49766
  version: "0.1.0",
@@ -52247,476 +52334,471 @@ var errors = [
52247
52334
  },
52248
52335
  {
52249
52336
  code: 6021,
52250
- name: "CloseShortImpossibleState",
52251
- msg: "Close short impossible state: current_total should always be greater than remaining_close_reduced_sol_with_fee"
52252
- },
52253
- {
52254
- code: 6022,
52255
52337
  name: "FeeSplitCalculationOverflow",
52256
52338
  msg: "Fee split calculation overflow"
52257
52339
  },
52258
52340
  {
52259
- code: 6023,
52341
+ code: 6022,
52260
52342
  name: "FeeAccumulationOverflow",
52261
52343
  msg: "Fee accumulation overflow"
52262
52344
  },
52263
52345
  {
52264
- code: 6024,
52346
+ code: 6023,
52265
52347
  name: "PartnerFeeAdditionOverflow",
52266
52348
  msg: "Partner fee addition overflow"
52267
52349
  },
52268
52350
  {
52269
- code: 6025,
52351
+ code: 6024,
52270
52352
  name: "BaseFeeAdditionOverflow",
52271
52353
  msg: "Base fee addition overflow"
52272
52354
  },
52273
52355
  {
52274
- code: 6026,
52356
+ code: 6025,
52275
52357
  name: "PoolFeeDeductionOverflow",
52276
52358
  msg: "Pool fee deduction overflow"
52277
52359
  },
52278
52360
  {
52279
- code: 6027,
52361
+ code: 6026,
52280
52362
  name: "FeeRandomDiscountOverflow",
52281
52363
  msg: "Fee random discount calculation overflow"
52282
52364
  },
52283
52365
  {
52284
- code: 6028,
52366
+ code: 6027,
52285
52367
  name: "SolReserveAdditionOverflow",
52286
52368
  msg: "SOL reserve addition overflow"
52287
52369
  },
52288
52370
  {
52289
- code: 6029,
52371
+ code: 6028,
52290
52372
  name: "SolReserveDeductionOverflow",
52291
52373
  msg: "SOL reserve deduction overflow"
52292
52374
  },
52293
52375
  {
52294
- code: 6030,
52376
+ code: 6029,
52295
52377
  name: "TokenReserveAdditionOverflow",
52296
52378
  msg: "Token reserve addition overflow"
52297
52379
  },
52298
52380
  {
52299
- code: 6031,
52381
+ code: 6030,
52300
52382
  name: "LamportsAdditionOverflow",
52301
52383
  msg: "Lamports addition overflow"
52302
52384
  },
52303
52385
  {
52304
- code: 6032,
52386
+ code: 6031,
52305
52387
  name: "LamportsDeductionOverflow",
52306
52388
  msg: "Lamports deduction overflow"
52307
52389
  },
52308
52390
  {
52309
- code: 6033,
52391
+ code: 6032,
52310
52392
  name: "DeadlineCalculationOverflow",
52311
52393
  msg: "Deadline calculation overflow"
52312
52394
  },
52313
52395
  {
52314
- code: 6034,
52396
+ code: 6033,
52315
52397
  name: "FeeDiscountFlagOverflow",
52316
52398
  msg: "Fee discount flag calculation overflow"
52317
52399
  },
52318
52400
  {
52319
- code: 6035,
52401
+ code: 6034,
52320
52402
  name: "Unauthorized",
52321
52403
  msg: "Unauthorized operation"
52322
52404
  },
52323
52405
  {
52324
- code: 6036,
52406
+ code: 6035,
52325
52407
  name: "RequiredParameter",
52326
52408
  msg: "All parameters are required during initialization"
52327
52409
  },
52328
52410
  {
52329
- code: 6037,
52411
+ code: 6036,
52330
52412
  name: "CurveCalculationError",
52331
52413
  msg: "Curve calculation error"
52332
52414
  },
52333
52415
  {
52334
- code: 6038,
52416
+ code: 6037,
52335
52417
  name: "InitialPriceCalculationError",
52336
52418
  msg: "Initial price calculation failed"
52337
52419
  },
52338
52420
  {
52339
- code: 6039,
52421
+ code: 6038,
52340
52422
  name: "BuyReserveRecalculationError",
52341
52423
  msg: "Reserve recalculation failed (after buy)"
52342
52424
  },
52343
52425
  {
52344
- code: 6040,
52426
+ code: 6039,
52345
52427
  name: "SellReserveRecalculationError",
52346
52428
  msg: "Reserve recalculation failed (after sell)"
52347
52429
  },
52348
52430
  {
52349
- code: 6041,
52431
+ code: 6040,
52350
52432
  name: "TotalAmountWithFeeError",
52351
52433
  msg: "Total amount with fee calculation failed"
52352
52434
  },
52353
52435
  {
52354
- code: 6042,
52436
+ code: 6041,
52355
52437
  name: "AmountAfterFeeError",
52356
52438
  msg: "Amount after fee calculation failed"
52357
52439
  },
52358
52440
  {
52359
- code: 6043,
52441
+ code: 6042,
52360
52442
  name: "BuyPriceRangeCalculationError",
52361
52443
  msg: "Buy price range calculation failed"
52362
52444
  },
52363
52445
  {
52364
- code: 6044,
52446
+ code: 6043,
52365
52447
  name: "SellPriceRangeCalculationError",
52366
52448
  msg: "Sell price range calculation failed"
52367
52449
  },
52368
52450
  {
52369
- code: 6045,
52451
+ code: 6044,
52370
52452
  name: "PriceAtStopLossBoundary",
52371
52453
  msg: "Price has reached stop-loss boundary, head order must be liquidated first"
52372
52454
  },
52373
52455
  {
52374
- code: 6046,
52456
+ code: 6045,
52375
52457
  name: "RemainingRangeCalculationError",
52376
52458
  msg: "Remaining range calculation failed"
52377
52459
  },
52378
52460
  {
52379
- code: 6047,
52461
+ code: 6046,
52380
52462
  name: "FullRangeCalculationError",
52381
52463
  msg: "Full range calculation failed"
52382
52464
  },
52383
52465
  {
52384
- code: 6048,
52466
+ code: 6047,
52385
52467
  name: "BuyFromPriceWithTokenNoneError",
52386
52468
  msg: "Curve function returned None: buy_from_price_with_token_output"
52387
52469
  },
52388
52470
  {
52389
- code: 6049,
52471
+ code: 6048,
52390
52472
  name: "SellFromPriceWithTokenNoneError",
52391
52473
  msg: "Curve function returned None: sell_from_price_with_token_input"
52392
52474
  },
52393
52475
  {
52394
- code: 6050,
52476
+ code: 6049,
52395
52477
  name: "ExceedsMaxSolAmount",
52396
52478
  msg: "Required SOL amount exceeds user-set maximum"
52397
52479
  },
52398
52480
  {
52399
- code: 6051,
52481
+ code: 6050,
52400
52482
  name: "InsufficientSolOutput",
52401
52483
  msg: "Insufficient SOL output"
52402
52484
  },
52403
52485
  {
52404
- code: 6052,
52486
+ code: 6051,
52405
52487
  name: "InsufficientRepayment",
52406
52488
  msg: "Insufficient proceeds to repay loan"
52407
52489
  },
52408
52490
  {
52409
- code: 6053,
52491
+ code: 6052,
52410
52492
  name: "InsufficientBorrowingReserve",
52411
52493
  msg: "Insufficient borrowing reserve"
52412
52494
  },
52413
52495
  {
52414
- code: 6054,
52496
+ code: 6053,
52415
52497
  name: "InsufficientTokenSale",
52416
52498
  msg: "Insufficient token sale amount"
52417
52499
  },
52418
52500
  {
52419
- code: 6055,
52501
+ code: 6054,
52420
52502
  name: "InsufficientLiquidity",
52421
52503
  msg: "Insufficient liquidity in current order"
52422
52504
  },
52423
52505
  {
52424
- code: 6056,
52506
+ code: 6055,
52425
52507
  name: "InsufficientMarketLiquidity",
52426
52508
  msg: "Insufficient market liquidity, cannot satisfy trade even after liquidating all stop-loss orders"
52427
52509
  },
52428
52510
  {
52429
- code: 6057,
52511
+ code: 6056,
52430
52512
  name: "TokenAmountDifferenceOutOfRange",
52431
52513
  msg: "Token amount difference exceeds valid range in margin trade"
52432
52514
  },
52433
52515
  {
52434
- code: 6058,
52516
+ code: 6057,
52435
52517
  name: "BorrowAmountMismatch",
52436
52518
  msg: "Borrow amount mismatch with locked tokens"
52437
52519
  },
52438
52520
  {
52439
- code: 6059,
52521
+ code: 6058,
52440
52522
  name: "CloseFeeCalculationError",
52441
52523
  msg: "Close fee calculation error"
52442
52524
  },
52443
52525
  {
52444
- code: 6060,
52526
+ code: 6059,
52445
52527
  name: "InsufficientMargin",
52446
52528
  msg: "Insufficient margin"
52447
52529
  },
52448
52530
  {
52449
- code: 6061,
52531
+ code: 6060,
52450
52532
  name: "InsufficientMinimumMargin",
52451
52533
  msg: "Margin below minimum requirement"
52452
52534
  },
52453
52535
  {
52454
- code: 6062,
52536
+ code: 6061,
52455
52537
  name: "InvalidAccountOwner",
52456
52538
  msg: "Invalid account owner"
52457
52539
  },
52458
52540
  {
52459
- code: 6063,
52541
+ code: 6062,
52460
52542
  name: "SellAmountExceedsOrderAmount",
52461
52543
  msg: "Sell amount exceeds order's token holdings"
52462
52544
  },
52463
52545
  {
52464
- code: 6064,
52546
+ code: 6063,
52465
52547
  name: "OrderNotExpiredMustCloseByOwner",
52466
52548
  msg: "Non-expired order must be closed by owner"
52467
52549
  },
52468
52550
  {
52469
- code: 6065,
52551
+ code: 6064,
52470
52552
  name: "SettlementAddressMustBeOwnerAddress",
52471
52553
  msg: "Settlement address must be owner address"
52472
52554
  },
52473
52555
  {
52474
- code: 6066,
52556
+ code: 6065,
52475
52557
  name: "BuyAmountExceedsOrderAmount",
52476
52558
  msg: "Buy amount exceeds order's token holdings"
52477
52559
  },
52478
52560
  {
52479
- code: 6067,
52561
+ code: 6066,
52480
52562
  name: "InsufficientTradeAmount",
52481
52563
  msg: "Trade amount below minimum requirement"
52482
52564
  },
52483
52565
  {
52484
- code: 6068,
52566
+ code: 6067,
52485
52567
  name: "SolAmountTooLarge",
52486
52568
  msg: "SOL amount exceeds maximum limit (10000000 SOL per transaction)"
52487
52569
  },
52488
52570
  {
52489
- code: 6069,
52571
+ code: 6068,
52490
52572
  name: "RemainingTokenAmountTooSmall",
52491
52573
  msg: "Remaining token amount below minimum trade requirement"
52492
52574
  },
52493
52575
  {
52494
- code: 6070,
52576
+ code: 6069,
52495
52577
  name: "TradeCooldownNotExpired",
52496
52578
  msg: "Trade cooldown period not expired, please try again later"
52497
52579
  },
52498
52580
  {
52499
- code: 6071,
52581
+ code: 6070,
52500
52582
  name: "ExceedApprovalAmount",
52501
52583
  msg: "Sell amount exceeds approved amount, please call approval function first"
52502
52584
  },
52503
52585
  {
52504
- code: 6072,
52586
+ code: 6071,
52505
52587
  name: "CooldownNotInitialized",
52506
52588
  msg: "Sell trade requires calling approval or buy function first to initialize cooldown PDA"
52507
52589
  },
52508
52590
  {
52509
- code: 6073,
52591
+ code: 6072,
52510
52592
  name: "CannotCloseCooldownWithBalance",
52511
52593
  msg: "Cannot close cooldown PDA with non-zero token balance"
52512
52594
  },
52513
52595
  {
52514
- code: 6074,
52596
+ code: 6073,
52515
52597
  name: "PriceCalculationError",
52516
52598
  msg: "Price calculation error"
52517
52599
  },
52518
52600
  {
52519
- code: 6075,
52601
+ code: 6074,
52520
52602
  name: "InvalidPartnerFeeRecipientAccount",
52521
52603
  msg: "Invalid partner fee recipient account"
52522
52604
  },
52523
52605
  {
52524
- code: 6076,
52606
+ code: 6075,
52525
52607
  name: "InvalidBaseFeeRecipientAccount",
52526
52608
  msg: "Invalid base fee recipient account"
52527
52609
  },
52528
52610
  {
52529
- code: 6077,
52611
+ code: 6076,
52530
52612
  name: "InvalidOrderbookAddress",
52531
52613
  msg: "Orderbook address does not match curve account orderbook"
52532
52614
  },
52533
52615
  {
52534
- code: 6078,
52616
+ code: 6077,
52535
52617
  name: "InvalidFeePercentage",
52536
52618
  msg: "Fee percentage must be between 0-100"
52537
52619
  },
52538
52620
  {
52539
- code: 6079,
52621
+ code: 6078,
52540
52622
  name: "InvalidFeeRate",
52541
52623
  msg: "Fee rate exceeds maximum limit (10%)"
52542
52624
  },
52543
52625
  {
52544
- code: 6080,
52626
+ code: 6079,
52545
52627
  name: "InvalidCustomFeeRate",
52546
52628
  msg: "Custom fee rate must be between 1000 (1%) and 5000 (5%)"
52547
52629
  },
52548
52630
  {
52549
- code: 6081,
52631
+ code: 6080,
52550
52632
  name: "InvalidBorrowDuration",
52551
52633
  msg: "Borrow duration out of valid range (3-30 days)"
52552
52634
  },
52553
52635
  {
52554
- code: 6082,
52636
+ code: 6081,
52555
52637
  name: "InvalidStopLossPrice",
52556
52638
  msg: "Stop loss price does not meet minimum interval requirement"
52557
52639
  },
52558
52640
  {
52559
- code: 6083,
52641
+ code: 6082,
52560
52642
  name: "NoProfitableFunds",
52561
52643
  msg: "No profitable funds to transfer"
52562
52644
  },
52563
52645
  {
52564
- code: 6084,
52646
+ code: 6083,
52565
52647
  name: "InsufficientPoolFunds",
52566
52648
  msg: "Insufficient pool funds"
52567
52649
  },
52568
52650
  {
52569
- code: 6085,
52651
+ code: 6084,
52570
52652
  name: "InsufficientPoolBalance",
52571
52653
  msg: "Pool SOL account balance would fall below minimum required balance"
52572
52654
  },
52573
52655
  {
52574
- code: 6086,
52656
+ code: 6085,
52575
52657
  name: "OrderBookManagerOverflow",
52576
52658
  msg: "Math operation overflow"
52577
52659
  },
52578
52660
  {
52579
- code: 6087,
52661
+ code: 6086,
52580
52662
  name: "OrderBookManagerInvalidSlotIndex",
52581
52663
  msg: "Invalid slot index"
52582
52664
  },
52583
52665
  {
52584
- code: 6088,
52666
+ code: 6087,
52585
52667
  name: "OrderBookManagerInvalidAccountData",
52586
52668
  msg: "Invalid account data"
52587
52669
  },
52588
52670
  {
52589
- code: 6089,
52671
+ code: 6088,
52590
52672
  name: "OrderBookManagerExceedsMaxCapacity",
52591
52673
  msg: "New capacity exceeds maximum limit"
52592
52674
  },
52593
52675
  {
52594
- code: 6090,
52676
+ code: 6089,
52595
52677
  name: "OrderBookManagerExceedsAccountSizeLimit",
52596
52678
  msg: "Account size exceeds 10MB limit"
52597
52679
  },
52598
52680
  {
52599
- code: 6091,
52681
+ code: 6090,
52600
52682
  name: "OrderBookManagerOrderIdMismatch",
52601
52683
  msg: "Order ID mismatch"
52602
52684
  },
52603
52685
  {
52604
- code: 6092,
52686
+ code: 6091,
52605
52687
  name: "OrderBookManagerEmptyOrderBook",
52606
52688
  msg: "Order book is empty"
52607
52689
  },
52608
52690
  {
52609
- code: 6093,
52691
+ code: 6092,
52610
52692
  name: "OrderBookManagerAccountNotWritable",
52611
52693
  msg: "Account is not writable"
52612
52694
  },
52613
52695
  {
52614
- code: 6094,
52696
+ code: 6093,
52615
52697
  name: "OrderBookManagerNotRentExempt",
52616
52698
  msg: "Account not rent-exempt"
52617
52699
  },
52618
52700
  {
52619
- code: 6095,
52701
+ code: 6094,
52620
52702
  name: "OrderBookManagerInvalidRentBalance",
52621
52703
  msg: "Invalid rent balance"
52622
52704
  },
52623
52705
  {
52624
- code: 6096,
52706
+ code: 6095,
52625
52707
  name: "OrderBookManagerInsufficientFunds",
52626
52708
  msg: "Insufficient funds"
52627
52709
  },
52628
52710
  {
52629
- code: 6097,
52711
+ code: 6096,
52630
52712
  name: "OrderBookManagerInvalidAccountOwner",
52631
52713
  msg: "OrderBook account owner mismatch"
52632
52714
  },
52633
52715
  {
52634
- code: 6098,
52716
+ code: 6097,
52635
52717
  name: "OrderBookManagerDataOutOfBounds",
52636
52718
  msg: "Data access out of bounds"
52637
52719
  },
52638
52720
  {
52639
- code: 6099,
52721
+ code: 6098,
52640
52722
  name: "NoValidInsertPosition",
52641
52723
  msg: "Cannot find valid insert position, all candidates failed due to price range overlap"
52642
52724
  },
52643
52725
  {
52644
- code: 6100,
52726
+ code: 6099,
52645
52727
  name: "EmptyCloseInsertIndices",
52646
52728
  msg: "close_insert_indices array cannot be empty"
52647
52729
  },
52648
52730
  {
52649
- code: 6101,
52731
+ code: 6100,
52650
52732
  name: "TooManyCloseInsertIndices",
52651
52733
  msg: "close_insert_indices array cannot exceed 20 elements"
52652
52734
  },
52653
52735
  {
52654
- code: 6102,
52736
+ code: 6101,
52655
52737
  name: "CloseOrderNotFound",
52656
52738
  msg: "Specified close order not found"
52657
52739
  },
52658
52740
  {
52659
- code: 6103,
52741
+ code: 6102,
52660
52742
  name: "LinkedListDeleteCountMismatch",
52661
52743
  msg: "Linked list delete count mismatch: count inconsistent before/after deletion"
52662
52744
  },
52663
52745
  {
52664
- code: 6104,
52746
+ code: 6103,
52665
52747
  name: "NameTooLong",
52666
52748
  msg: "Token name too long, max 32 bytes"
52667
52749
  },
52668
52750
  {
52669
- code: 6105,
52751
+ code: 6104,
52670
52752
  name: "NameEmpty",
52671
52753
  msg: "Token name cannot be empty"
52672
52754
  },
52673
52755
  {
52674
- code: 6106,
52756
+ code: 6105,
52675
52757
  name: "SymbolTooLong",
52676
52758
  msg: "Token symbol too long, max 10 bytes"
52677
52759
  },
52678
52760
  {
52679
- code: 6107,
52761
+ code: 6106,
52680
52762
  name: "SymbolEmpty",
52681
52763
  msg: "Token symbol cannot be empty"
52682
52764
  },
52683
52765
  {
52684
- code: 6108,
52766
+ code: 6107,
52685
52767
  name: "UriTooLong",
52686
52768
  msg: "URI too long, max 200 bytes"
52687
52769
  },
52688
52770
  {
52689
- code: 6109,
52771
+ code: 6108,
52690
52772
  name: "UriEmpty",
52691
52773
  msg: "URI cannot be empty"
52692
52774
  },
52693
52775
  {
52694
- code: 6110,
52776
+ code: 6109,
52695
52777
  name: "IncompleteAdvancedPoolParams",
52696
52778
  msg: "Incomplete advanced pool parameters: custom_lp_sol, custom_lp_token, custom_borrow_ratio, custom_borrow_duration must be provided together"
52697
52779
  },
52698
52780
  {
52699
- code: 6111,
52781
+ code: 6110,
52700
52782
  name: "InvalidInitialVirtualSol",
52701
52783
  msg: "Initial virtual SOL out of valid range"
52702
52784
  },
52703
52785
  {
52704
- code: 6112,
52786
+ code: 6111,
52705
52787
  name: "InvalidInitialVirtualToken",
52706
52788
  msg: "Initial virtual Token out of valid range"
52707
52789
  },
52708
52790
  {
52709
- code: 6113,
52791
+ code: 6112,
52710
52792
  name: "InvalidBorrowPoolRatio",
52711
52793
  msg: "Borrow pool ratio out of valid range"
52712
52794
  },
52713
52795
  {
52714
- code: 6114,
52796
+ code: 6113,
52715
52797
  name: "BorrowTokenCalculationOverflow",
52716
52798
  msg: "Borrow pool token amount calculation overflow"
52717
52799
  },
52718
52800
  {
52719
- code: 6115,
52801
+ code: 6114,
52720
52802
  name: "BorrowTokenAmountZero",
52721
52803
  msg: "Borrow pool token amount cannot be zero"
52722
52804
  }
@@ -53629,7 +53711,7 @@ const DEFAULT_NETWORKS = {
53629
53711
  MAINNET: {
53630
53712
  name: 'mainnet-beta',
53631
53713
  defaultDataSource: 'fast',
53632
- solanaEndpoint: 'https://melissa-ali6qz-fast-mainnet.helius-rpc.com',
53714
+ solanaEndpoint: 'https://solana-rpc.pinpet.fun',
53633
53715
  pinPetFastApiUrl: 'https://api.pinpet.fun/',
53634
53716
  feeRecipient: 'CmDe8JRAPJ7QpZNCb4ArVEyzyxYoCNL7WZw5qXLePULn',
53635
53717
  baseFeeRecipient: '2xhAfEfnH8wg7ZGujSijJi4Zt4ge1ZuwMypo7etntgXA',
@@ -53638,7 +53720,7 @@ const DEFAULT_NETWORKS = {
53638
53720
  DEVNET: {
53639
53721
  name: 'devnet',
53640
53722
  defaultDataSource: 'fast',
53641
- solanaEndpoint: 'https://devnet.helius-rpc.com/?api-key=666f279b-0b08-41cd-97f4-461811d7fc7a',
53723
+ solanaEndpoint: 'https://lu-ura5lv-fast-devnet.helius-rpc.com',
53642
53724
  pinPetFastApiUrl: 'https://devtestapi.pinpet.fun',
53643
53725
  feeRecipient: 'GesAj2dTn2wdNcxj4x8qsqS9aNRVPBPkE76aaqg7skxu',
53644
53726
  baseFeeRecipient: '5YHi1HsxobLiTD6NQfHJQpoPoRjMuNyXp4RroTvR6dKi',