pinpet-sdk 2.1.8 → 2.1.9

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.
@@ -41935,9 +41935,11 @@ class CurveAMM$7 {
41935
41935
 
41936
41936
  /**
41937
41937
  * Minimum price that can appear, below this price may cause overflow
41938
+ * Note: With dynamic liquidity pools, prices can be much smaller (e.g., 3e-10)
41939
+ * Reduced from 1e-9 to 1e-12 to support wider range of pool configurations
41938
41940
  * @type {Decimal}
41939
41941
  */
41940
- static INITIAL_MIN_PRICE_DECIMAL = new Decimal('0.000000001');
41942
+ static INITIAL_MIN_PRICE_DECIMAL = new Decimal('0.000000000001'); // 1e-12
41941
41943
 
41942
41944
  /**
41943
41945
  * Decimal representation of precision factor = 10^23
@@ -42743,9 +42745,83 @@ class CurveAMM$7 {
42743
42745
  return [endPriceU128, solAmountU64];
42744
42746
  }
42745
42747
 
42748
+ /**
42749
+ * 基于起始价格和期望token输出量计算需要的SOL输入量和结束价格(带自定义流动池参数)
42750
+ * Based on starting price and desired token output, calculate required SOL input and ending price (with custom pool params)
42751
+ *
42752
+ * @param {bigint|string|number} startLowPrice - Starting price (lower)
42753
+ * @param {bigint|string|number} tokenOutputAmount - Desired token amount to obtain
42754
+ * @param {string|number|Decimal} initialVirtualSol - Initial virtual SOL reserve
42755
+ * @param {string|number|Decimal} initialVirtualToken - Initial virtual token reserve
42756
+ * @returns {[bigint, bigint]|null} Returns [price after transaction, SOL amount to pay] on success, null on failure
42757
+ * Price rounded down, SOL amount rounded up
42758
+ */
42759
+ static buyFromPriceWithTokenOutputWithParams(startLowPrice, tokenOutputAmount, initialVirtualSol, initialVirtualToken) {
42760
+ // Convert to Decimal for calculation
42761
+ const startPriceDec = this.u128ToDecimal(startLowPrice);
42762
+ const tokenOutputDec = this.u64ToTokenDecimal(tokenOutputAmount);
42763
+
42764
+ // Check if input parameters are valid
42765
+ if (startPriceDec.lte(0)) {
42766
+ return null;
42767
+ }
42768
+
42769
+ // If token output amount is 0, return unchanged price and SOL input of 0
42770
+ if (tokenOutputDec.eq(0)) {
42771
+ const endPriceU128 = this.decimalToU128(startPriceDec);
42772
+ if (endPriceU128 === null) return null;
42773
+ return [endPriceU128, 0n];
42774
+ }
42775
+
42776
+ if (tokenOutputDec.lt(0)) {
42777
+ return null;
42778
+ }
42779
+
42780
+ // Use custom pool parameters to calculate k value
42781
+ const k = this.calculateK(initialVirtualSol, initialVirtualToken);
42782
+
42783
+ // Calculate reserves for starting state
42784
+ const startReserves = this.calculateReservesByPrice(startPriceDec, k);
42785
+ if (!startReserves) return null;
42786
+
42787
+ const [startSolReserve, startTokenReserve] = startReserves;
42788
+
42789
+ // Calculate token reserves for ending state
42790
+ const endTokenReserve = startTokenReserve.sub(tokenOutputDec);
42791
+
42792
+ // Check if token reserves are sufficient
42793
+ if (endTokenReserve.lte(0)) {
42794
+ return null;
42795
+ }
42796
+
42797
+ // Calculate SOL reserve for ending state using AMM formula
42798
+ const endSolReserve = k.div(endTokenReserve);
42799
+
42800
+ // Calculate required SOL input amount
42801
+ const solInputAmount = endSolReserve.sub(startSolReserve);
42802
+
42803
+ // Calculate ending price
42804
+ const endPrice = endSolReserve.div(endTokenReserve);
42805
+
42806
+ // Check if calculation results are valid
42807
+ if (solInputAmount.lte(0) || endPrice.lte(0)) {
42808
+ return null;
42809
+ }
42810
+
42811
+ // Convert back to appropriate types with required rounding
42812
+ const endPriceU128 = this.decimalToU128(endPrice); // Price rounded down
42813
+ const solAmountU64 = this.solDecimalToU64Ceil(solInputAmount); // SOL rounded up
42814
+
42815
+ if (endPriceU128 === null || solAmountU64 === null) {
42816
+ return null;
42817
+ }
42818
+
42819
+ return [endPriceU128, solAmountU64];
42820
+ }
42821
+
42746
42822
  /**
42747
42823
  * Calculate required token input amount and ending price based on starting price and expected SOL output amount
42748
- *
42824
+ *
42749
42825
  * @param {bigint|string|number} startHighPrice - Starting price
42750
42826
  * @param {bigint|string|number} solOutputAmount - Desired SOL amount to obtain
42751
42827
  * @returns {[bigint, bigint]|null} Returns [price after transaction, token amount to pay] on success, null on failure
@@ -42814,9 +42890,83 @@ class CurveAMM$7 {
42814
42890
  return [endPriceU128, tokenAmountU64];
42815
42891
  }
42816
42892
 
42893
+ /**
42894
+ * 基于起始价格和期望SOL输出量计算需要的token输入量和结束价格(带自定义流动池参数)
42895
+ * Based on starting price and desired SOL output, calculate required token input and ending price (with custom pool params)
42896
+ *
42897
+ * @param {bigint|string|number} startHighPrice - Starting price (higher)
42898
+ * @param {bigint|string|number} solOutputAmount - Desired SOL amount to obtain
42899
+ * @param {string|number|Decimal} initialVirtualSol - Initial virtual SOL reserve
42900
+ * @param {string|number|Decimal} initialVirtualToken - Initial virtual token reserve
42901
+ * @returns {[bigint, bigint]|null} Returns [price after transaction, token amount to pay] on success, null on failure
42902
+ * Price rounded down, token amount rounded up
42903
+ */
42904
+ static sellFromPriceWithSolOutputWithParams(startHighPrice, solOutputAmount, initialVirtualSol, initialVirtualToken) {
42905
+ // Convert to Decimal for calculation
42906
+ const startPriceDec = this.u128ToDecimal(startHighPrice);
42907
+ const solOutputDec = this.u64ToSolDecimal(solOutputAmount);
42908
+
42909
+ // Check if input parameters are valid
42910
+ if (startPriceDec.lte(0)) {
42911
+ return null;
42912
+ }
42913
+
42914
+ // If SOL output amount is 0, return unchanged price and token input of 0
42915
+ if (solOutputDec.eq(0)) {
42916
+ const endPriceU128 = this.decimalToU128(startPriceDec);
42917
+ if (endPriceU128 === null) return null;
42918
+ return [endPriceU128, 0n];
42919
+ }
42920
+
42921
+ if (solOutputDec.lt(0)) {
42922
+ return null;
42923
+ }
42924
+
42925
+ // Use custom pool parameters to calculate k value
42926
+ const k = this.calculateK(initialVirtualSol, initialVirtualToken);
42927
+
42928
+ // Calculate reserves for starting state
42929
+ const startReserves = this.calculateReservesByPrice(startPriceDec, k);
42930
+ if (!startReserves) return null;
42931
+
42932
+ const [startSolReserve, startTokenReserve] = startReserves;
42933
+
42934
+ // Calculate SOL reserves for ending state
42935
+ const endSolReserve = startSolReserve.sub(solOutputDec);
42936
+
42937
+ // Check if SOL reserves are sufficient
42938
+ if (endSolReserve.lte(0)) {
42939
+ return null;
42940
+ }
42941
+
42942
+ // Calculate token reserves for ending state according to AMM formula
42943
+ const endTokenReserve = k.div(endSolReserve);
42944
+
42945
+ // Calculate required token input amount
42946
+ const tokenInputAmount = endTokenReserve.sub(startTokenReserve);
42947
+
42948
+ // Calculate ending price
42949
+ const endPrice = endSolReserve.div(endTokenReserve);
42950
+
42951
+ // Check if calculation results are valid
42952
+ if (tokenInputAmount.lte(0) || endPrice.lte(0)) {
42953
+ return null;
42954
+ }
42955
+
42956
+ // Convert back to appropriate types with required rounding
42957
+ const endPriceU128 = this.decimalToU128(endPrice); // Price rounded down
42958
+ const tokenAmountU64 = this.tokenDecimalToU64Ceil(tokenInputAmount); // Token rounded up
42959
+
42960
+ if (endPriceU128 === null || tokenAmountU64 === null) {
42961
+ return null;
42962
+ }
42963
+
42964
+ return [endPriceU128, tokenAmountU64];
42965
+ }
42966
+
42817
42967
  /**
42818
42968
  * Calculate remaining amount after deducting fees
42819
- *
42969
+ *
42820
42970
  * @param {bigint|string|number} amount - Original amount
42821
42971
  * @param {number} fee - Fee rate, expressed with FEE_DENOMINATOR as denominator
42822
42972
  * Example: 1000 represents 1% fee (1000/100000)
@@ -45915,7 +46065,7 @@ const CurveAMM$4 = curve_amm;
45915
46065
  * @throws {Error} 无限流动性计算失败:最大价格流动性计算异常 Infinite liquidity calculation failure: max price liquidity calculation exception
45916
46066
  * @throws {Error} 订单数据格式错误:订单对象缺少必需字段 Order data format error: order object missing required fields
45917
46067
  */
45918
- function calcLiqTokenBuy$1(price, buyTokenAmount, orders, onceMaxOrder, passOrder = null) {
46068
+ function calcLiqTokenBuy$1(price, buyTokenAmount, orders, onceMaxOrder, passOrder = null, initialVirtualSol = null, initialVirtualToken = null) {
45919
46069
  // 由于是买入操作 肯定拿的是 up_orders 方向的 订单 lock_lp_start_price < lock_lp_end_price
45920
46070
  // 并且 lock_lp_start_price 在 orders 中是从小到大排序的
45921
46071
 
@@ -45932,6 +46082,9 @@ function calcLiqTokenBuy$1(price, buyTokenAmount, orders, onceMaxOrder, passOrde
45932
46082
  if (!onceMaxOrder || onceMaxOrder <= 0) {
45933
46083
  throw new Error('参数验证错误:onceMaxOrder 必须是正数 Parameter validation error: onceMaxOrder must be a positive number');
45934
46084
  }
46085
+ if (initialVirtualSol === null || initialVirtualToken === null) {
46086
+ throw new Error('参数验证错误:initialVirtualSol 和 initialVirtualToken 不能为空 Parameter validation error: initialVirtualSol and initialVirtualToken cannot be null');
46087
+ }
45935
46088
 
45936
46089
  const result = {
45937
46090
  free_lp_sol_amount_sum: 0n, // 间隙中可使用的sol流动性数量
@@ -45962,7 +46115,14 @@ function calcLiqTokenBuy$1(price, buyTokenAmount, orders, onceMaxOrder, passOrde
45962
46115
 
45963
46116
  try {
45964
46117
  const priceBigInt = BigInt(price);
45965
- [, result.ideal_lp_sol_amount] = CurveAMM$4.buyFromPriceWithTokenOutput(priceBigInt, buyTokenAmountBigInt);
46118
+ const initialVirtualSolBigInt = BigInt(initialVirtualSol.toString());
46119
+ const initialVirtualTokenBigInt = BigInt(initialVirtualToken.toString());
46120
+ [, result.ideal_lp_sol_amount] = CurveAMM$4.buyFromPriceWithTokenOutputWithParams(
46121
+ priceBigInt,
46122
+ buyTokenAmountBigInt,
46123
+ initialVirtualSolBigInt,
46124
+ initialVirtualTokenBigInt
46125
+ );
45966
46126
  // console.log(`理想计算: 当前价格=${priceBigInt}, 目标代币=${buyTokenAmountBigInt}, 理想SOL=${result.ideal_lp_sol_amount}`);
45967
46127
  } catch (error) {
45968
46128
  throw new Error(`buy流动性计算错误:理想流动性计算失败 Liquidity calculation error: Ideal liquidity calculation failed - ${error.message}`);
@@ -46268,7 +46428,7 @@ function calcLiqTokenBuy$1(price, buyTokenAmount, orders, onceMaxOrder, passOrde
46268
46428
  * @throws {Error} 无限流动性计算失败:最小价格流动性计算异常 Infinite liquidity calculation failure: min price liquidity calculation exception
46269
46429
  * @throws {Error} 订单数据格式错误:订单对象缺少必需字段 Order data format error: order object missing required fields
46270
46430
  */
46271
- function calcLiqTokenSell$1(price, sellTokenAmount, orders, onceMaxOrder, passOrder = null) {
46431
+ function calcLiqTokenSell$1(price, sellTokenAmount, orders, onceMaxOrder, passOrder = null, initialVirtualSol = null, initialVirtualToken = null) {
46272
46432
  // 由于是卖出操作 肯定拿的是 down_orders 方向的 订单 lock_lp_start_price > lock_lp_end_price
46273
46433
  // 并且 lock_lp_start_price 在 orders 中是从大到小排序的
46274
46434
 
@@ -46285,6 +46445,9 @@ function calcLiqTokenSell$1(price, sellTokenAmount, orders, onceMaxOrder, passOr
46285
46445
  if (!onceMaxOrder || onceMaxOrder <= 0) {
46286
46446
  throw new Error('参数验证错误:onceMaxOrder 必须是正数 Parameter validation error: onceMaxOrder must be a positive number');
46287
46447
  }
46448
+ if (initialVirtualSol === null || initialVirtualToken === null) {
46449
+ throw new Error('参数验证错误:initialVirtualSol 和 initialVirtualToken 不能为空 Parameter validation error: initialVirtualSol and initialVirtualToken cannot be null');
46450
+ }
46288
46451
 
46289
46452
  const result = {
46290
46453
  free_lp_sol_amount_sum: 0n, // 间隙中可使用的sol流动性数量
@@ -46311,7 +46474,14 @@ function calcLiqTokenSell$1(price, sellTokenAmount, orders, onceMaxOrder, passOr
46311
46474
  // 计算理想情况下卖出能获得的SOL数量
46312
46475
  try {
46313
46476
  const priceBigInt = BigInt(price);
46314
- [, result.ideal_lp_sol_amount] = CurveAMM$4.sellFromPriceWithTokenInput(priceBigInt, sellTokenAmountBigInt);
46477
+ const initialVirtualSolBigInt = BigInt(initialVirtualSol.toString());
46478
+ const initialVirtualTokenBigInt = BigInt(initialVirtualToken.toString());
46479
+ [, result.ideal_lp_sol_amount] = CurveAMM$4.sellFromPriceWithTokenInputWithParams(
46480
+ priceBigInt,
46481
+ sellTokenAmountBigInt,
46482
+ initialVirtualSolBigInt,
46483
+ initialVirtualTokenBigInt
46484
+ );
46315
46485
  // console.log(`理想计算: 当前价格=${priceBigInt}, 卖出代币=${sellTokenAmountBigInt}, 理想SOL=${result.ideal_lp_sol_amount}`);
46316
46486
  } catch (error) {
46317
46487
  throw new Error(`sell流动性计算错误:理想流动性计算失败 Liquidity calculation error: Ideal liquidity calculation failed - ${error.message}`);
@@ -46319,7 +46489,14 @@ function calcLiqTokenSell$1(price, sellTokenAmount, orders, onceMaxOrder, passOr
46319
46489
 
46320
46490
  // orders 长度为0 时要单独计算
46321
46491
  if (orders.length === 0) {
46322
- const sellResult = CurveAMM$4.sellFromPriceToPrice(BigInt(price), CurveAMM$4.MIN_U128_PRICE);
46492
+ const initialVirtualSolBigInt = BigInt(initialVirtualSol.toString());
46493
+ const initialVirtualTokenBigInt = BigInt(initialVirtualToken.toString());
46494
+ const sellResult = CurveAMM$4.sellFromPriceToPriceWithParams(
46495
+ BigInt(price),
46496
+ CurveAMM$4.MIN_U128_PRICE,
46497
+ initialVirtualSolBigInt,
46498
+ initialVirtualTokenBigInt
46499
+ );
46323
46500
  if (sellResult) {
46324
46501
  [result.free_lp_token_amount_sum, result.free_lp_sol_amount_sum] = sellResult;
46325
46502
  } else {
@@ -46601,19 +46778,29 @@ async function simulateTokenBuy$1(mint, buyTokenAmount, passOrder = null, lastPr
46601
46778
  orders = ordersData.data.orders.slice(0, this.sdk.MAX_ORDERS_COUNT + 1);
46602
46779
  }
46603
46780
 
46781
+ // 获取动态流动池参数
46782
+ let curveData;
46783
+ try {
46784
+ curveData = await this.sdk.chain.getCurveAccount(mint);
46785
+ } catch (error) {
46786
+ throw new Error(`Failed to get curve account data: ${error.message}`);
46787
+ }
46788
+
46604
46789
  // console.log('simulateTokenBuy 获取的数据:');
46605
46790
  // console.log('价格:', price);
46606
46791
  // console.log('订单数量:', orders.length);
46607
46792
  // orders.forEach((order, i) => console.log(`订单${i}: start=${order.lock_lp_start_price}, end=${order.lock_lp_end_price}, sol=${order.lock_lp_sol_amount}, token=${order.lock_lp_token_amount}`));
46608
46793
 
46609
- // 调用 calcLiqTokenBuy 进行流动性计算
46794
+ // 调用 calcLiqTokenBuy 进行流动性计算(传入动态流动池参数)
46610
46795
  try {
46611
46796
  const liqResult = calcLiqTokenBuy(
46612
46797
  price,
46613
- buyTokenAmount,
46798
+ buyTokenAmount,
46614
46799
  orders,
46615
46800
  this.sdk.MAX_ORDERS_COUNT,
46616
- passOrder
46801
+ passOrder,
46802
+ curveData.initialVirtualSol,
46803
+ curveData.initialVirtualToken
46617
46804
  );
46618
46805
 
46619
46806
  // console.log('\n=== calcLiqTokenBuy 返回结果 ===');
@@ -46662,7 +46849,9 @@ async function simulateTokenBuy$1(mint, buyTokenAmount, passOrder = null, lastPr
46662
46849
  suggestedAmount,
46663
46850
  orders,
46664
46851
  this.sdk.MAX_ORDERS_COUNT,
46665
- passOrder
46852
+ passOrder,
46853
+ curveData.initialVirtualSol,
46854
+ curveData.initialVirtualToken
46666
46855
  );
46667
46856
 
46668
46857
  const recalcRealSol = BigInt(recalcResult.real_lp_sol_amount);
@@ -46744,19 +46933,29 @@ async function simulateTokenSell$1(mint, sellTokenAmount, passOrder = null, last
46744
46933
  orders = ordersData.data.orders.slice(0, this.sdk.MAX_ORDERS_COUNT + 1);
46745
46934
  }
46746
46935
 
46936
+ // 获取动态流动池参数
46937
+ let curveData;
46938
+ try {
46939
+ curveData = await this.sdk.chain.getCurveAccount(mint);
46940
+ } catch (error) {
46941
+ throw new Error(`Failed to get curve account data: ${error.message}`);
46942
+ }
46943
+
46747
46944
  // console.log('simulateTokenSell 获取的数据:');
46748
46945
  // console.log('价格:', price);
46749
46946
  // console.log('订单数量:', orders.length);
46750
46947
  // orders.forEach((order, i) => console.log(`订单${i}: start=${order.lock_lp_start_price}, end=${order.lock_lp_end_price}, sol=${order.lock_lp_sol_amount}, token=${order.lock_lp_token_amount}`));
46751
46948
 
46752
- // 调用 calcLiqTokenSell 进行流动性计算
46949
+ // 调用 calcLiqTokenSell 进行流动性计算(传入动态流动池参数)
46753
46950
  try {
46754
46951
  const liqResult = calcLiqTokenSell(
46755
46952
  price,
46756
46953
  sellTokenAmount,
46757
46954
  orders,
46758
46955
  this.sdk.MAX_ORDERS_COUNT,
46759
- passOrder
46956
+ passOrder,
46957
+ curveData.initialVirtualSol,
46958
+ curveData.initialVirtualToken
46760
46959
  );
46761
46960
 
46762
46961
  // console.log('\n=== calcLiqTokenSell 返回结果 ===');
@@ -46805,7 +47004,9 @@ async function simulateTokenSell$1(mint, sellTokenAmount, passOrder = null, last
46805
47004
  suggestedAmount,
46806
47005
  orders,
46807
47006
  this.sdk.MAX_ORDERS_COUNT,
46808
- passOrder
47007
+ passOrder,
47008
+ curveData.initialVirtualSol,
47009
+ curveData.initialVirtualToken
46809
47010
  );
46810
47011
 
46811
47012
  const recalcRealSol = BigInt(recalcResult.real_lp_sol_amount);