@meteora-ag/cp-amm-sdk 1.0.1-rc.33 → 1.0.1-rc.34

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/index.mjs CHANGED
@@ -21,7 +21,7 @@ var __async = (__this, __arguments, generator) => {
21
21
  };
22
22
 
23
23
  // src/CpAmm.ts
24
- import { Program, BN as BN9 } from "@coral-xyz/anchor";
24
+ import { Program, BN as BN10 } from "@coral-xyz/anchor";
25
25
  import { NATIVE_MINT as NATIVE_MINT2, TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRAM_ID2 } from "@solana/spl-token";
26
26
  import invariant from "invariant";
27
27
 
@@ -7140,8 +7140,49 @@ function calculateTransferFeeExcludedAmount(transferFeeIncludedAmount, mint, cur
7140
7140
  };
7141
7141
  }
7142
7142
 
7143
- // src/CpAmm.ts
7143
+ // src/helpers/vestings.ts
7144
+ import { BN as BN9 } from "@coral-xyz/anchor";
7144
7145
  import { min } from "bn.js";
7146
+ function isVestingComplete(vestingData, currentPoint) {
7147
+ const cliffPoint = vestingData.cliffPoint;
7148
+ const periodFrequency = vestingData.periodFrequency;
7149
+ const numberOfPeriods = vestingData.numberOfPeriod;
7150
+ const endPoint = cliffPoint.add(periodFrequency.muln(numberOfPeriods));
7151
+ return currentPoint.gte(endPoint);
7152
+ }
7153
+ function getTotalLockedLiquidity(vestingData) {
7154
+ return vestingData.cliffUnlockLiquidity.add(
7155
+ vestingData.liquidityPerPeriod.mul(new BN9(vestingData.numberOfPeriod))
7156
+ );
7157
+ }
7158
+ function getAvailableVestingLiquidity(vestingData, currentPoint) {
7159
+ const {
7160
+ cliffPoint,
7161
+ periodFrequency,
7162
+ cliffUnlockLiquidity,
7163
+ liquidityPerPeriod,
7164
+ numberOfPeriod,
7165
+ totalReleasedLiquidity
7166
+ } = vestingData;
7167
+ if (currentPoint < cliffPoint) {
7168
+ return new BN9(0);
7169
+ }
7170
+ if (periodFrequency.isZero()) {
7171
+ return cliffUnlockLiquidity.sub(totalReleasedLiquidity);
7172
+ }
7173
+ let passedPeriod = new BN9(currentPoint).sub(cliffPoint).div(periodFrequency);
7174
+ passedPeriod = min(passedPeriod, new BN9(numberOfPeriod));
7175
+ const unlockedLiquidity = cliffUnlockLiquidity.add(
7176
+ passedPeriod.mul(liquidityPerPeriod)
7177
+ );
7178
+ const availableReleasingLiquidity = unlockedLiquidity.sub(
7179
+ totalReleasedLiquidity
7180
+ );
7181
+ return availableReleasingLiquidity;
7182
+ }
7183
+
7184
+ // src/CpAmm.ts
7185
+ import { min as min2 } from "bn.js";
7145
7186
  var CpAmm = class {
7146
7187
  constructor(connection) {
7147
7188
  this._program = new Program(cp_amm_default, {
@@ -7371,6 +7412,33 @@ var CpAmm = class {
7371
7412
  }).instruction();
7372
7413
  });
7373
7414
  }
7415
+ /**
7416
+ * Builds an instruction to refresh vesting for a position
7417
+ * @param params Parameters required for the refresh vesting instruction
7418
+ * @returns Transaction instruction or null if no vestings to refresh
7419
+ */
7420
+ buildRefreshVestingInstruction(params) {
7421
+ return __async(this, null, function* () {
7422
+ const { owner, position, positionNftAccount, pool, vestingAccounts } = params;
7423
+ if (vestingAccounts.length == 0) {
7424
+ return null;
7425
+ }
7426
+ return yield this._program.methods.refreshVesting().accountsPartial({
7427
+ position,
7428
+ positionNftAccount,
7429
+ pool,
7430
+ owner
7431
+ }).remainingAccounts(
7432
+ vestingAccounts.map((pubkey) => {
7433
+ return {
7434
+ isSigner: false,
7435
+ isWritable: true,
7436
+ pubkey
7437
+ };
7438
+ })
7439
+ ).instruction();
7440
+ });
7441
+ }
7374
7442
  /**
7375
7443
  * Fetches the Config state of the program.
7376
7444
  * @param config - Public key of the config account.
@@ -7518,6 +7586,44 @@ var CpAmm = class {
7518
7586
  );
7519
7587
  return totalLockedLiquidity.gtn(0);
7520
7588
  }
7589
+ isPermanentLockedPosition(positionState) {
7590
+ return positionState.permanentLockedLiquidity.gtn(0);
7591
+ }
7592
+ /**
7593
+ * Checks if a position can be unlocked based on its locking state and vesting schedules.
7594
+ *
7595
+ * This method evaluates whether a position is eligible for operations that require
7596
+ * unlocked liquidity, such as removing all liquidity or closing the position. It checks both
7597
+ * permanent locks and time-based vesting schedules.
7598
+ *
7599
+ * @private
7600
+ * @param {PositionState} positionState - The current state of the position
7601
+ * @param {Array<{account: PublicKey; vestingState: VestingState}>} vestings - Array of vesting accounts and their states
7602
+ * @param {BN} currentPoint - Current timestamp or slot number (depending on activation type of pool)
7603
+ *
7604
+ * @returns {Object} Result object containing unlock status and reason
7605
+ * @returns {boolean} result.canUnlock - Whether the position can be unlocked
7606
+ * @returns {string|undefined} result.reason - Reason why position cannot be unlocked (if applicable)
7607
+ */
7608
+ canUnlockPosition(positionState, vestings, currentPoint) {
7609
+ if (vestings.length > 0) {
7610
+ if (this.isPermanentLockedPosition(positionState)) {
7611
+ return {
7612
+ canUnlock: false,
7613
+ reason: "Position is permanently locked"
7614
+ };
7615
+ }
7616
+ for (const vesting of vestings) {
7617
+ if (!isVestingComplete(vesting.vestingState, currentPoint)) {
7618
+ return {
7619
+ canUnlock: false,
7620
+ reason: "Position has incomplete vesting schedule"
7621
+ };
7622
+ }
7623
+ }
7624
+ }
7625
+ return { canUnlock: true };
7626
+ }
7521
7627
  isPoolExist(pool) {
7522
7628
  return __async(this, null, function* () {
7523
7629
  const poolState = yield this._program.account.pool.fetchNullable(pool);
@@ -7590,22 +7696,25 @@ var CpAmm = class {
7590
7696
  aToB,
7591
7697
  collectFeeMode
7592
7698
  );
7593
- let actualAmoutOut = amountOut;
7699
+ let actualAmountOut = amountOut;
7594
7700
  if (outputTokenInfo) {
7595
- actualAmoutOut = calculateTransferFeeExcludedAmount(
7701
+ actualAmountOut = calculateTransferFeeExcludedAmount(
7596
7702
  amountOut,
7597
7703
  outputTokenInfo.mint,
7598
7704
  outputTokenInfo.currentEpoch
7599
7705
  ).amount;
7600
7706
  }
7601
- const minSwapOutAmount = getMinAmountWithSlippage(actualAmoutOut, slippage);
7707
+ const minSwapOutAmount = getMinAmountWithSlippage(
7708
+ actualAmountOut,
7709
+ slippage
7710
+ );
7602
7711
  return {
7603
7712
  swapInAmount: inAmount,
7604
7713
  consumedInAmount: actualAmountIn,
7605
- swapOutAmount: actualAmoutOut,
7714
+ swapOutAmount: actualAmountOut,
7606
7715
  minSwapOutAmount,
7607
7716
  totalFee,
7608
- priceImpact: getPriceImpact(minSwapOutAmount, actualAmoutOut)
7717
+ priceImpact: getPriceImpact(minSwapOutAmount, actualAmountOut)
7609
7718
  };
7610
7719
  });
7611
7720
  }
@@ -7662,7 +7771,7 @@ var CpAmm = class {
7662
7771
  0 /* Up */
7663
7772
  )
7664
7773
  };
7665
- const rawOutputAmount = new BN9(rawAmount(liquidityDelta));
7774
+ const rawOutputAmount = new BN10(rawAmount(liquidityDelta));
7666
7775
  const outputAmount = outputTokenInfo ? calculateTransferFeeIncludedAmount(
7667
7776
  rawOutputAmount,
7668
7777
  outputTokenInfo.mint,
@@ -7772,7 +7881,7 @@ var CpAmm = class {
7772
7881
  tokenAInfo,
7773
7882
  tokenBInfo
7774
7883
  } = params;
7775
- if (tokenAAmount.eq(new BN9(0)) && tokenBAmount.eq(new BN9(0))) {
7884
+ if (tokenAAmount.eq(new BN10(0)) && tokenBAmount.eq(new BN10(0))) {
7776
7885
  throw new Error("Invalid input amount");
7777
7886
  }
7778
7887
  const actualAmountAIn = tokenAInfo ? tokenAAmount.sub(
@@ -7782,13 +7891,13 @@ var CpAmm = class {
7782
7891
  tokenAInfo.currentEpoch
7783
7892
  ).transferFee
7784
7893
  ) : tokenAAmount;
7785
- const actualAmountBIn = tokenBInfo ? tokenAAmount.sub(
7894
+ const actualAmountBIn = tokenBInfo ? tokenBAmount.sub(
7786
7895
  calculateTransferFeeIncludedAmount(
7787
7896
  tokenBAmount,
7788
7897
  tokenBInfo.mint,
7789
7898
  tokenBInfo.currentEpoch
7790
7899
  ).transferFee
7791
- ) : tokenAAmount;
7900
+ ) : tokenBAmount;
7792
7901
  const initSqrtPrice = calculateInitSqrtPrice(
7793
7902
  tokenAAmount,
7794
7903
  tokenBAmount,
@@ -7805,7 +7914,7 @@ var CpAmm = class {
7805
7914
  minSqrtPrice,
7806
7915
  initSqrtPrice
7807
7916
  );
7808
- const liquidityDelta = min(
7917
+ const liquidityDelta = min2(
7809
7918
  liquidityDeltaFromAmountA,
7810
7919
  liquidityDeltaFromAmountB
7811
7920
  );
@@ -8121,7 +8230,8 @@ var CpAmm = class {
8121
8230
  tokenAVault,
8122
8231
  tokenBVault,
8123
8232
  tokenAProgram,
8124
- tokenBProgram
8233
+ tokenBProgram,
8234
+ vestings
8125
8235
  } = params;
8126
8236
  const {
8127
8237
  tokenAAta: tokenAAccount,
@@ -8141,6 +8251,16 @@ var CpAmm = class {
8141
8251
  const closeWrappedSOLIx = yield unwrapSOLInstruction(owner);
8142
8252
  closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
8143
8253
  }
8254
+ if (vestings.length > 0) {
8255
+ const refreshVestingInstruction = yield this.buildRefreshVestingInstruction({
8256
+ owner,
8257
+ position,
8258
+ positionNftAccount,
8259
+ pool,
8260
+ vestingAccounts: vestings.map((item) => item.account)
8261
+ });
8262
+ refreshVestingInstruction && preInstructions.push(refreshVestingInstruction);
8263
+ }
8144
8264
  return yield this._program.methods.removeLiquidity({
8145
8265
  liquidityDelta,
8146
8266
  tokenAAmountThreshold,
@@ -8181,7 +8301,8 @@ var CpAmm = class {
8181
8301
  tokenAVault,
8182
8302
  tokenBVault,
8183
8303
  tokenAProgram,
8184
- tokenBProgram
8304
+ tokenBProgram,
8305
+ vestings
8185
8306
  } = params;
8186
8307
  const {
8187
8308
  tokenAAta: tokenAAccount,
@@ -8201,6 +8322,16 @@ var CpAmm = class {
8201
8322
  const closeWrappedSOLIx = yield unwrapSOLInstruction(owner);
8202
8323
  closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
8203
8324
  }
8325
+ if (vestings.length > 0) {
8326
+ const refreshVestingInstruction = yield this.buildRefreshVestingInstruction({
8327
+ owner,
8328
+ position,
8329
+ positionNftAccount,
8330
+ pool,
8331
+ vestingAccounts: vestings.map((item) => item.account)
8332
+ });
8333
+ refreshVestingInstruction && preInstructions.push(refreshVestingInstruction);
8334
+ }
8204
8335
  const removeAllLiquidityInstruction = yield this.buildRemoveAllLiquidityInstruction({
8205
8336
  poolAuthority: this.poolAuthority,
8206
8337
  owner,
@@ -8358,21 +8489,8 @@ var CpAmm = class {
8358
8489
  */
8359
8490
  refreshVesting(params) {
8360
8491
  return __async(this, null, function* () {
8361
- const { owner, position, positionNftAccount, pool, vestings } = params;
8362
- return yield this._program.methods.refreshVesting().accountsPartial({
8363
- position,
8364
- positionNftAccount,
8365
- pool,
8366
- owner
8367
- }).remainingAccounts(
8368
- vestings.map((pubkey) => {
8369
- return {
8370
- isSigner: false,
8371
- isWritable: true,
8372
- pubkey
8373
- };
8374
- })
8375
- ).transaction();
8492
+ const instruction = yield this.buildRefreshVestingInstruction(params);
8493
+ return new Transaction().add(instruction);
8376
8494
  });
8377
8495
  }
8378
8496
  /**
@@ -8470,13 +8588,19 @@ var CpAmm = class {
8470
8588
  positionState,
8471
8589
  poolState,
8472
8590
  tokenAAmountThreshold,
8473
- tokenBAmountThreshold
8591
+ tokenBAmountThreshold,
8592
+ vestings,
8593
+ currentPoint
8474
8594
  } = params;
8475
8595
  const { nftMint: positionNftMint, pool } = positionState;
8476
8596
  const { tokenAMint, tokenBMint, tokenAVault, tokenBVault } = poolState;
8477
- const isLockedPosition = this.isLockedPosition(positionState);
8478
- if (isLockedPosition) {
8479
- throw Error("position must be unlocked");
8597
+ const { canUnlock, reason } = this.canUnlockPosition(
8598
+ positionState,
8599
+ vestings,
8600
+ currentPoint
8601
+ );
8602
+ if (!canUnlock) {
8603
+ throw new Error(`Cannot remove liquidity: ${reason}`);
8480
8604
  }
8481
8605
  const tokenAProgram = getTokenProgram(poolState.tokenAFlag);
8482
8606
  const tokenBProgram = getTokenProgram(poolState.tokenBFlag);
@@ -8498,6 +8622,16 @@ var CpAmm = class {
8498
8622
  const closeWrappedSOLIx = yield unwrapSOLInstruction(owner);
8499
8623
  closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
8500
8624
  }
8625
+ if (vestings.length > 0) {
8626
+ const refreshVestingInstruction = yield this.buildRefreshVestingInstruction({
8627
+ owner,
8628
+ position,
8629
+ positionNftAccount,
8630
+ pool,
8631
+ vestingAccounts: vestings.map((item) => item.account)
8632
+ });
8633
+ refreshVestingInstruction && preInstructions.push(refreshVestingInstruction);
8634
+ }
8501
8635
  const transaction = new Transaction();
8502
8636
  if (preInstructions.length > 0) {
8503
8637
  transaction.add(...preInstructions);
@@ -8576,13 +8710,19 @@ var CpAmm = class {
8576
8710
  tokenAAmountAddLiquidityThreshold,
8577
8711
  tokenBAmountAddLiquidityThreshold,
8578
8712
  tokenAAmountRemoveLiquidityThreshold,
8579
- tokenBAmountRemoveLiquidityThreshold
8713
+ tokenBAmountRemoveLiquidityThreshold,
8714
+ positionBVestings,
8715
+ currentPoint
8580
8716
  } = params;
8581
- const isLockedPosition = this.isLockedPosition(positionBState);
8582
- if (isLockedPosition) {
8583
- throw Error("position must be unlocked");
8717
+ const { canUnlock, reason } = this.canUnlockPosition(
8718
+ positionBState,
8719
+ positionBVestings,
8720
+ currentPoint
8721
+ );
8722
+ if (!canUnlock) {
8723
+ throw new Error(`Cannot remove liquidity: ${reason}`);
8584
8724
  }
8585
- const postionBLiquidityDelta = positionBState.unlockedLiquidity;
8725
+ const positionBLiquidityDelta = positionBState.unlockedLiquidity;
8586
8726
  const pool = positionBState.pool;
8587
8727
  const { tokenAMint, tokenBMint, tokenAVault, tokenBVault } = poolState;
8588
8728
  const tokenAProgram = getTokenProgram(poolState.tokenAFlag);
@@ -8605,6 +8745,16 @@ var CpAmm = class {
8605
8745
  const closeWrappedSOLIx = yield unwrapSOLInstruction(owner);
8606
8746
  closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx);
8607
8747
  }
8748
+ if (positionBVestings.length > 0) {
8749
+ const refreshVestingInstruction = yield this.buildRefreshVestingInstruction({
8750
+ owner,
8751
+ position: positionB,
8752
+ positionNftAccount: positionBNftAccount,
8753
+ pool,
8754
+ vestingAccounts: positionBVestings.map((item) => item.account)
8755
+ });
8756
+ refreshVestingInstruction && preInstructions.push(refreshVestingInstruction);
8757
+ }
8608
8758
  const transaction = new Transaction();
8609
8759
  if (preInstructions.length > 0) {
8610
8760
  transaction.add(...preInstructions);
@@ -8656,7 +8806,7 @@ var CpAmm = class {
8656
8806
  tokenBVault,
8657
8807
  tokenAProgram,
8658
8808
  tokenBProgram,
8659
- liquidityDelta: postionBLiquidityDelta,
8809
+ liquidityDelta: positionBLiquidityDelta,
8660
8810
  tokenAAmountThreshold: tokenAAmountAddLiquidityThreshold,
8661
8811
  tokenBAmountThreshold: tokenBAmountAddLiquidityThreshold
8662
8812
  });
@@ -8924,6 +9074,7 @@ export {
8924
9074
  getAllUserPositionNftAccount,
8925
9075
  getAmountAFromLiquidityDelta,
8926
9076
  getAmountBFromLiquidityDelta,
9077
+ getAvailableVestingLiquidity,
8927
9078
  getBaseFeeNumerator,
8928
9079
  getDynamicFeeNumerator,
8929
9080
  getEstimatedComputeUnitIxWithBuffer,
@@ -8945,7 +9096,9 @@ export {
8945
9096
  getSwapAmount,
8946
9097
  getTokenDecimals,
8947
9098
  getTokenProgram,
9099
+ getTotalLockedLiquidity,
8948
9100
  getUnClaimReward,
9101
+ isVestingComplete,
8949
9102
  mulDiv,
8950
9103
  positionByPoolFilter,
8951
9104
  pow,