@kamino-finance/kliquidity-sdk 8.3.1 → 8.4.0

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.
Files changed (91) hide show
  1. package/dist/Kamino.d.ts +16 -14
  2. package/dist/Kamino.d.ts.map +1 -1
  3. package/dist/Kamino.js +114 -125
  4. package/dist/Kamino.js.map +1 -1
  5. package/dist/constants/numericalValues.d.ts +3 -0
  6. package/dist/constants/numericalValues.d.ts.map +1 -1
  7. package/dist/constants/numericalValues.js +4 -1
  8. package/dist/constants/numericalValues.js.map +1 -1
  9. package/dist/rebalance_methods/autodriftRebalance.d.ts.map +1 -1
  10. package/dist/rebalance_methods/autodriftRebalance.js +10 -10
  11. package/dist/rebalance_methods/autodriftRebalance.js.map +1 -1
  12. package/dist/rebalance_methods/driftRebalance.d.ts.map +1 -1
  13. package/dist/rebalance_methods/driftRebalance.js +10 -10
  14. package/dist/rebalance_methods/driftRebalance.js.map +1 -1
  15. package/dist/rebalance_methods/expanderRebalance.d.ts.map +1 -1
  16. package/dist/rebalance_methods/expanderRebalance.js +3 -4
  17. package/dist/rebalance_methods/expanderRebalance.js.map +1 -1
  18. package/dist/rebalance_methods/pricePercentageRebalance.d.ts.map +1 -1
  19. package/dist/rebalance_methods/pricePercentageRebalance.js +5 -6
  20. package/dist/rebalance_methods/pricePercentageRebalance.js.map +1 -1
  21. package/dist/rebalance_methods/pricePercentageWithResetRebalance.d.ts.map +1 -1
  22. package/dist/rebalance_methods/pricePercentageWithResetRebalance.js +5 -6
  23. package/dist/rebalance_methods/pricePercentageWithResetRebalance.js.map +1 -1
  24. package/dist/rebalance_methods/takeProfitRebalance.d.ts.map +1 -1
  25. package/dist/rebalance_methods/takeProfitRebalance.js +5 -5
  26. package/dist/rebalance_methods/takeProfitRebalance.js.map +1 -1
  27. package/dist/services/JupService.d.ts.map +1 -1
  28. package/dist/services/MeteoraService.d.ts.map +1 -1
  29. package/dist/services/MeteoraService.js +4 -1
  30. package/dist/services/MeteoraService.js.map +1 -1
  31. package/dist/services/OrcaService.d.ts +7 -11
  32. package/dist/services/OrcaService.d.ts.map +1 -1
  33. package/dist/services/OrcaService.js +133 -101
  34. package/dist/services/OrcaService.js.map +1 -1
  35. package/dist/services/OrcaWhirlpoolsResponse.d.ts +63 -92
  36. package/dist/services/OrcaWhirlpoolsResponse.d.ts.map +1 -1
  37. package/dist/services/RaydiumService.d.ts.map +1 -1
  38. package/dist/services/RaydiumService.js +7 -1
  39. package/dist/services/RaydiumService.js.map +1 -1
  40. package/dist/utils/farms.d.ts +1 -0
  41. package/dist/utils/farms.d.ts.map +1 -0
  42. package/dist/utils/farms.js +2 -0
  43. package/dist/utils/farms.js.map +1 -0
  44. package/dist/utils/index.d.ts +1 -0
  45. package/dist/utils/index.d.ts.map +1 -1
  46. package/dist/utils/index.js +1 -0
  47. package/dist/utils/index.js.map +1 -1
  48. package/dist/utils/lookupTable.d.ts.map +1 -1
  49. package/dist/utils/lookupTable.js +1 -1
  50. package/dist/utils/lookupTable.js.map +1 -1
  51. package/dist/utils/orca.d.ts +37 -1
  52. package/dist/utils/orca.d.ts.map +1 -1
  53. package/dist/utils/orca.js +242 -0
  54. package/dist/utils/orca.js.map +1 -1
  55. package/dist/utils/tokenUtils.d.ts +5 -5
  56. package/dist/utils/tokenUtils.d.ts.map +1 -1
  57. package/dist/utils/tokenUtils.js +11 -7
  58. package/dist/utils/tokenUtils.js.map +1 -1
  59. package/dist/utils/transactions.d.ts.map +1 -1
  60. package/dist/utils/types.d.ts +5 -0
  61. package/dist/utils/types.d.ts.map +1 -1
  62. package/dist/utils/types.js.map +1 -1
  63. package/dist/utils/utils.d.ts +0 -1
  64. package/dist/utils/utils.d.ts.map +1 -1
  65. package/dist/utils/utils.js +3 -4
  66. package/dist/utils/utils.js.map +1 -1
  67. package/dist/utils/whirlpools.d.ts +12 -1
  68. package/dist/utils/whirlpools.d.ts.map +1 -1
  69. package/dist/utils/whirlpools.js +30 -29
  70. package/dist/utils/whirlpools.js.map +1 -1
  71. package/package.json +10 -9
  72. package/src/Kamino.ts +271 -215
  73. package/src/constants/numericalValues.ts +5 -0
  74. package/src/rebalance_methods/autodriftRebalance.ts +30 -22
  75. package/src/rebalance_methods/driftRebalance.ts +30 -22
  76. package/src/rebalance_methods/expanderRebalance.ts +7 -4
  77. package/src/rebalance_methods/pricePercentageRebalance.ts +13 -6
  78. package/src/rebalance_methods/pricePercentageWithResetRebalance.ts +13 -6
  79. package/src/rebalance_methods/takeProfitRebalance.ts +13 -5
  80. package/src/services/MeteoraService.ts +5 -2
  81. package/src/services/OrcaService.ts +163 -126
  82. package/src/services/OrcaWhirlpoolsResponse.ts +69 -101
  83. package/src/services/RaydiumService.ts +8 -2
  84. package/src/utils/farms.ts +0 -0
  85. package/src/utils/index.ts +1 -0
  86. package/src/utils/lookupTable.ts +2 -2
  87. package/src/utils/orca.ts +377 -1
  88. package/src/utils/tokenUtils.ts +5 -5
  89. package/src/utils/types.ts +7 -0
  90. package/src/utils/utils.ts +2 -4
  91. package/src/utils/whirlpools.ts +50 -31
package/dist/Kamino.js CHANGED
@@ -11,9 +11,7 @@ const accounts_1 = require("./@codegen/kliquidity/accounts");
11
11
  const decimal_js_1 = __importDefault(require("decimal.js"));
12
12
  const instructions_1 = require("./@codegen/whirlpools/instructions");
13
13
  const accounts_2 = require("./@codegen/whirlpools/accounts");
14
- const whirlpool_sdk_1 = require("@orca-so/whirlpool-sdk");
15
- const orca_dal_1 = require("@orca-so/whirlpool-sdk/dist/dal/orca-dal");
16
- const orca_position_1 = require("@orca-so/whirlpool-sdk/dist/position/orca-position");
14
+ const whirlpools_core_1 = require("@orca-so/whirlpools-core");
17
15
  const models_1 = require("./models");
18
16
  const scope_sdk_1 = require("@kamino-finance/scope-sdk");
19
17
  const utils_1 = require("./utils");
@@ -24,7 +22,6 @@ const constants_1 = require("./constants");
24
22
  const types_1 = require("./@codegen/kliquidity/types");
25
23
  const accounts_3 = require("./@codegen/raydium/accounts");
26
24
  const services_1 = require("./services");
27
- const add_liquidity_1 = require("@orca-so/whirlpool-sdk/dist/position/quotes/add-liquidity");
28
25
  const StrategyConfigOption_1 = require("./@codegen/kliquidity/types/StrategyConfigOption");
29
26
  const DefaultStrategyConfig_1 = require("./constants/DefaultStrategyConfig");
30
27
  const pubkeys_1 = require("./constants/pubkeys");
@@ -92,7 +89,7 @@ class Kamino {
92
89
  this._globalConfig = globalConfig ? globalConfig : (0, compat_1.fromLegacyPublicKey)(this._config.kamino.globalConfig);
93
90
  }
94
91
  this._scope = new scope_sdk_1.Scope(cluster, rpc);
95
- this._orcaService = new services_1.OrcaService(rpc, legacyConnection, cluster, whirlpoolProgramId);
92
+ this._orcaService = new services_1.OrcaService(rpc, legacyConnection, whirlpoolProgramId);
96
93
  this._raydiumService = new services_1.RaydiumService(rpc, legacyConnection, raydiumProgramId);
97
94
  this._meteoraService = new MeteoraService_1.MeteoraService(rpc, meteoraProgramId);
98
95
  if (jupBaseAPI) {
@@ -100,6 +97,7 @@ class Kamino {
100
97
  }
101
98
  }
102
99
  getConnection = () => this._rpc;
100
+ getLegacyConnection = () => this._legacyConnection;
103
101
  getProgramID = () => this._kliquidityProgramId;
104
102
  setGlobalConfig = (globalConfig) => {
105
103
  this._globalConfig = globalConfig;
@@ -435,7 +433,7 @@ class Kamino {
435
433
  if (pools.length === 0) {
436
434
  throw new Error(`No pool found for ${poolTokenA.toString()} and ${poolTokenB.toString()}`);
437
435
  }
438
- return pools[0].price;
436
+ return Number(pools[0].price);
439
437
  }
440
438
  else if (dex === 'RAYDIUM') {
441
439
  const pools = await this.getRaydiumPoolsForTokens(poolTokenA, poolTokenB);
@@ -490,7 +488,7 @@ class Kamino {
490
488
  let pool = pubkeys_1.DEFAULT_PUBLIC_KEY;
491
489
  const orcaPools = await this.getOrcaPoolsForTokens(poolTokenA, poolTokenB);
492
490
  orcaPools.forEach((element) => {
493
- if (element.lpFeeRate * CreationParameters_1.FullBPS === feeBPS.toNumber()) {
491
+ if (element.feeRate * CreationParameters_1.FullBPS === feeBPS.toNumber()) {
494
492
  pool = (0, kit_1.address)(element.address);
495
493
  }
496
494
  });
@@ -541,19 +539,19 @@ class Kamino {
541
539
  const genericPoolInfos = await Promise.all(pools.map(async (pool) => {
542
540
  const positionsCount = new decimal_js_1.default(await this.getPositionsCountForPool(dex, (0, kit_1.address)(pool.address)));
543
541
  // read price from pool
544
- const poolData = await this._orcaService.getPool((0, kit_1.address)(pool.address));
542
+ const poolData = await this._orcaService.getOrcaWhirlpool((0, kit_1.address)(pool.address));
545
543
  if (!poolData) {
546
544
  throw new Error(`Pool ${pool.address} not found`);
547
545
  }
548
546
  const poolInfo = {
549
547
  dex,
550
548
  address: (0, kit_1.address)(pool.address),
551
- price: (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(poolData.sqrtPrice, pool.tokenA.decimals, pool.tokenB.decimals),
552
- tokenMintA: (0, kit_1.address)(pool.tokenA.mint),
553
- tokenMintB: (0, kit_1.address)(pool.tokenB.mint),
554
- tvl: pool.tvl ? new decimal_js_1.default(pool.tvl) : undefined,
555
- feeRate: new decimal_js_1.default(pool.lpFeeRate).mul(CreationParameters_1.FullBPS),
556
- volumeOnLast7d: pool.volume ? new decimal_js_1.default(pool.volume.week) : undefined,
549
+ price: new decimal_js_1.default((0, whirlpools_core_1.sqrtPriceToPrice)(BigInt(poolData.sqrtPrice), pool.tokenA.decimals, pool.tokenB.decimals)),
550
+ tokenMintA: (0, kit_1.address)(pool.tokenMintA),
551
+ tokenMintB: (0, kit_1.address)(pool.tokenMintB),
552
+ tvl: pool.tvlUsdc ? new decimal_js_1.default(pool.tvlUsdc) : undefined,
553
+ feeRate: new decimal_js_1.default(pool.feeRate).mul(CreationParameters_1.FullBPS),
554
+ volumeOnLast7d: pool.stats['7d'] ? new decimal_js_1.default(pool.stats['7d'].volume) : undefined,
557
555
  tickSpacing: new decimal_js_1.default(pool.tickSpacing),
558
556
  positions: positionsCount,
559
557
  };
@@ -613,9 +611,9 @@ class Kamino {
613
611
  const poolTokenAString = poolTokenA.toString();
614
612
  const poolTokenBString = poolTokenB.toString();
615
613
  const whirlpools = await this._orcaService.getOrcaWhirlpools();
616
- whirlpools.whirlpools.forEach((element) => {
617
- if ((element.tokenA.mint === poolTokenAString && element.tokenB.mint === poolTokenBString) ||
618
- (element.tokenA.mint === poolTokenBString && element.tokenB.mint === poolTokenAString))
614
+ whirlpools.forEach((element) => {
615
+ if ((element.tokenMintA === poolTokenAString && element.tokenMintB === poolTokenBString) ||
616
+ (element.tokenMintA === poolTokenBString && element.tokenMintB === poolTokenAString))
619
617
  pools.push(element);
620
618
  });
621
619
  return pools;
@@ -690,7 +688,7 @@ class Kamino {
690
688
  filters.push({
691
689
  memcmp: {
692
690
  offset: 8n,
693
- bytes: strategyFilters.owner,
691
+ bytes: strategyFilters.owner.toString(),
694
692
  encoding: 'base58',
695
693
  },
696
694
  });
@@ -759,7 +757,7 @@ class Kamino {
759
757
  },
760
758
  {
761
759
  memcmp: {
762
- bytes: kTokenMint,
760
+ bytes: kTokenMint.toString(),
763
761
  offset: 720n,
764
762
  encoding: 'base58',
765
763
  },
@@ -1034,12 +1032,12 @@ class Kamino {
1034
1032
  const computedHoldings = this.getStrategyHoldingsUsd(tokenHoldings.available.a, tokenHoldings.available.b, tokenHoldings.invested.a, tokenHoldings.invested.b, new decimal_js_1.default(strategy.tokenAMintDecimals.toString()), new decimal_js_1.default(strategy.tokenBMintDecimals.toString()), strategyPrices.aPrice, strategyPrices.bPrice);
1035
1033
  const decimalsA = strategy.tokenAMintDecimals.toNumber();
1036
1034
  const decimalsB = strategy.tokenBMintDecimals.toNumber();
1037
- const poolPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(pool.sqrtPrice, decimalsA, decimalsB);
1035
+ const poolPrice = new decimal_js_1.default((0, whirlpools_core_1.sqrtPriceToPrice)(BigInt(pool.sqrtPrice.toString()), decimalsA, decimalsB));
1038
1036
  const twapPrice = strategyPrices.aTwapPrice !== null && strategyPrices.bTwapPrice !== null
1039
1037
  ? strategyPrices.aTwapPrice.div(strategyPrices.bTwapPrice)
1040
1038
  : null;
1041
- const upperPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(position.tickUpperIndex, decimalsA, decimalsB);
1042
- const lowerPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(position.tickLowerIndex, decimalsA, decimalsB);
1039
+ const upperPrice = new decimal_js_1.default((0, whirlpools_core_1.tickIndexToPrice)(position.tickUpperIndex, decimalsA, decimalsB));
1040
+ const lowerPrice = new decimal_js_1.default((0, whirlpools_core_1.tickIndexToPrice)(position.tickLowerIndex, decimalsA, decimalsB));
1043
1041
  let lowerResetPrice = null;
1044
1042
  let upperResetPrice = null;
1045
1043
  const dex = (0, utils_1.numberToDex)(strategy.strategyDex.toNumber());
@@ -1063,7 +1061,7 @@ class Kamino {
1063
1061
  const quote = (0, whirlpools_1.getRemoveLiquidityQuote)({
1064
1062
  positionAddress: strategy.position,
1065
1063
  liquidity: position.liquidity,
1066
- slippageTolerance: whirlpool_sdk_1.Percentage.fromFraction(0, 1000),
1064
+ slippageTolerance: { numerator: constants_1.ZERO_BN, denominator: new bn_js_1.default(1000) },
1067
1065
  sqrtPrice: pool.sqrtPrice,
1068
1066
  tickLowerIndex: position.tickLowerIndex,
1069
1067
  tickUpperIndex: position.tickUpperIndex,
@@ -1435,7 +1433,10 @@ class Kamino {
1435
1433
  //datasize:165 filter selects all token accounts, memcmp filter selects based on the mint address withing each token account
1436
1434
  return this._rpc
1437
1435
  .getProgramAccounts(token_1.TOKEN_PROGRAM_ADDRESS, {
1438
- filters: [{ dataSize: 165n }, { memcmp: { offset: 0n, bytes: shareMint, encoding: 'base58' } }],
1436
+ filters: [
1437
+ { dataSize: 165n },
1438
+ { memcmp: { offset: 0n, bytes: shareMint.toString(), encoding: 'base58' } },
1439
+ ],
1439
1440
  encoding: 'jsonParsed',
1440
1441
  })
1441
1442
  .send();
@@ -1447,7 +1448,10 @@ class Kamino {
1447
1448
  //how to get all token accounts for specific wallet: https://spl.solana.com/token#finding-all-token-accounts-for-a-wallet
1448
1449
  return this._rpc
1449
1450
  .getProgramAccounts(token_1.TOKEN_PROGRAM_ADDRESS, {
1450
- filters: [{ dataSize: 165n }, { memcmp: { offset: 32n, bytes: wallet, encoding: 'base58' } }],
1451
+ filters: [
1452
+ { dataSize: 165n },
1453
+ { memcmp: { offset: 32n, bytes: wallet.toString(), encoding: 'base58' } },
1454
+ ],
1451
1455
  encoding: 'jsonParsed',
1452
1456
  })
1453
1457
  .send();
@@ -1526,8 +1530,8 @@ class Kamino {
1526
1530
  if (!position) {
1527
1531
  return { lowerPrice: utils_1.ZERO, upperPrice: utils_1.ZERO };
1528
1532
  }
1529
- const lowerPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(position.tickLowerIndex, decimalsA, decimalsB);
1530
- const upperPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(position.tickUpperIndex, decimalsA, decimalsB);
1533
+ const lowerPrice = new decimal_js_1.default((0, whirlpools_core_1.tickIndexToPrice)(position.tickLowerIndex, decimalsA, decimalsB));
1534
+ const upperPrice = new decimal_js_1.default((0, whirlpools_core_1.tickIndexToPrice)(position.tickUpperIndex, decimalsA, decimalsB));
1531
1535
  const positionRange = { lowerPrice, upperPrice };
1532
1536
  return positionRange;
1533
1537
  };
@@ -1539,8 +1543,8 @@ class Kamino {
1539
1543
  if (!position) {
1540
1544
  return { lowerPrice: utils_1.ZERO, upperPrice: utils_1.ZERO };
1541
1545
  }
1542
- const lowerPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex), decimalsA, decimalsB);
1543
- const upperPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex), decimalsA, decimalsB);
1546
+ const lowerPrice = lib_1.SqrtPriceMath.sqrtPriceX64ToPrice(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex), decimalsA, decimalsB);
1547
+ const upperPrice = lib_1.SqrtPriceMath.sqrtPriceX64ToPrice(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex), decimalsA, decimalsB);
1544
1548
  const positionRange = { lowerPrice, upperPrice };
1545
1549
  return positionRange;
1546
1550
  };
@@ -1603,6 +1607,9 @@ class Kamino {
1603
1607
  }, {});
1604
1608
  return whirlpoolMap;
1605
1609
  };
1610
+ getAllWhirlpoolsFromAPI = async (tokens = []) => {
1611
+ return await this._orcaService.getOrcaWhirlpools(tokens);
1612
+ };
1606
1613
  /**
1607
1614
  * Get a list of Orca positions from public keys
1608
1615
  * @param positions
@@ -2941,8 +2948,8 @@ class Kamino {
2941
2948
  };
2942
2949
  };
2943
2950
  getStartEndTicketIndexProgramAddressesOrca = async (whirlpool, whirlpoolState, tickLowerIndex, tickUpperIndex) => {
2944
- const startTickIndex = (0, whirlpool_sdk_1.getStartTickIndex)(tickLowerIndex, whirlpoolState.tickSpacing, 0);
2945
- const endTickIndex = (0, whirlpool_sdk_1.getStartTickIndex)(tickUpperIndex, whirlpoolState.tickSpacing, 0);
2951
+ const startTickIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)(tickLowerIndex, whirlpoolState.tickSpacing);
2952
+ const endTickIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)(tickUpperIndex, whirlpoolState.tickSpacing);
2946
2953
  const [lowerTickPubkey, lowerTickBump] = await (0, kit_1.getProgramDerivedAddress)({
2947
2954
  seeds: [Buffer.from('tick_array'), addressEncoder.encode(whirlpool), Buffer.from(startTickIndex.toString())],
2948
2955
  programAddress: this._orcaService.getWhirlpoolProgramId(),
@@ -3090,8 +3097,8 @@ class Kamino {
3090
3097
  const isRebalancing = status.discriminator === StrategyStatus_1.Rebalancing.discriminator;
3091
3098
  const decimalsA = await (0, utils_1.getMintDecimals)(this._rpc, whirlpool.tokenMintA);
3092
3099
  const decimalsB = await (0, utils_1.getMintDecimals)(this._rpc, whirlpool.tokenMintB);
3093
- const tickLowerIndex = (0, whirlpool_sdk_1.getNextValidTickIndex)((0, whirlpool_sdk_1.priceToTickIndex)(priceLower, decimalsA, decimalsB), whirlpool.tickSpacing);
3094
- const tickUpperIndex = (0, whirlpool_sdk_1.getNextValidTickIndex)((0, whirlpool_sdk_1.priceToTickIndex)(priceUpper, decimalsA, decimalsB), whirlpool.tickSpacing);
3100
+ const tickLowerIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)((0, whirlpools_core_1.priceToTickIndex)(priceLower.toNumber(), decimalsA, decimalsB), whirlpool.tickSpacing);
3101
+ const tickUpperIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)((0, whirlpools_core_1.priceToTickIndex)(priceUpper.toNumber(), decimalsA, decimalsB), whirlpool.tickSpacing);
3095
3102
  const { position, positionBump, positionMetadata } = await this.getMetadataProgramAddressesOrca(positionMint.address);
3096
3103
  const positionTokenAccount = await (0, utils_1.getAssociatedTokenAddress)(positionMint.address, baseVaultAuthority);
3097
3104
  const args = {
@@ -3610,7 +3617,7 @@ class Kamino {
3610
3617
  if (dex === 'ORCA') {
3611
3618
  const { whirlpool: whilrpoolState } = await this.getWhirlpoolStateIfNotFetched(pool);
3612
3619
  if (rebalanceTypeKind.kind === types_1.RebalanceType.Drift.kind) {
3613
- processedRebalanceParams[0] = new decimal_js_1.default((0, whirlpool_sdk_1.getNearestValidTickIndexFromTickIndex)(rebalanceParams[0].toNumber(), whilrpoolState.tickSpacing));
3620
+ processedRebalanceParams[0] = new decimal_js_1.default((0, utils_1.getNearestValidTickIndexFromTickIndex)(rebalanceParams[0].toNumber(), whilrpoolState.tickSpacing));
3614
3621
  }
3615
3622
  }
3616
3623
  return processedRebalanceParams;
@@ -3805,7 +3812,7 @@ class Kamino {
3805
3812
  case types_1.RebalanceType.Expander.kind:
3806
3813
  return (0, rebalance_methods_1.getPositionRangeFromExpanderParams)(price, rebalanceParams[0], rebalanceParams[1]);
3807
3814
  case types_1.RebalanceType.Autodrift.kind:
3808
- const currentTickIndex = (0, whirlpool_sdk_1.priceToTickIndex)(price, tokenADecimals, tokenBDecimals);
3815
+ const currentTickIndex = (0, whirlpools_core_1.priceToTickIndex)(price.toNumber(), tokenADecimals, tokenBDecimals);
3809
3816
  const startMidTick = new decimal_js_1.default(currentTickIndex);
3810
3817
  return (0, autodriftRebalance_1.getPositionRangeFromAutodriftParams)(dex, tokenADecimals, tokenBDecimals, startMidTick, rebalanceParams[1], rebalanceParams[2], tickSpacing);
3811
3818
  default:
@@ -3816,11 +3823,11 @@ class Kamino {
3816
3823
  const strategyWithAddress = await this.getStrategyStateIfNotFetched(strategy);
3817
3824
  const pool = strategyWithAddress.strategy.pool;
3818
3825
  const dex = (0, utils_1.numberToDex)(strategyWithAddress.strategy.strategyDex.toNumber());
3819
- return this.getCurrentPriceFromPool(dex, pool);
3826
+ return this.getCurrentPriceFromPool(dex, pool, strategyWithAddress.strategy.tokenAMintDecimals.toNumber(), strategyWithAddress.strategy.tokenBMintDecimals.toNumber());
3820
3827
  }
3821
- async getCurrentPriceFromPool(dex, pool) {
3828
+ async getCurrentPriceFromPool(dex, pool, tokenADecimals, tokenBDecimals) {
3822
3829
  if (dex === 'ORCA') {
3823
- return this.getOrcaPoolPrice(pool);
3830
+ return this.getOrcaPoolPrice(pool, tokenADecimals, tokenBDecimals);
3824
3831
  }
3825
3832
  else if (dex === 'RAYDIUM') {
3826
3833
  return this.getRaydiumPoolPrice(pool);
@@ -4116,9 +4123,9 @@ class Kamino {
4116
4123
  /**
4117
4124
  * Read the pool price for a specific dex and pool
4118
4125
  */
4119
- async getPoolPrice(dex, pool) {
4126
+ async getPoolPrice(dex, pool, tokenADecimals, tokenBDecimals) {
4120
4127
  if (dex === 'ORCA') {
4121
- return this.getOrcaPoolPrice(pool);
4128
+ return this.getOrcaPoolPrice(pool, tokenADecimals, tokenBDecimals);
4122
4129
  }
4123
4130
  else if (dex === 'RAYDIUM') {
4124
4131
  return this.getRaydiumPoolPrice(pool);
@@ -4130,12 +4137,22 @@ class Kamino {
4130
4137
  throw new Error(`Invalid dex ${dex}`);
4131
4138
  }
4132
4139
  }
4133
- async getOrcaPoolPrice(pool) {
4134
- const poolData = await this._orcaService.getPool(pool);
4135
- if (!poolData) {
4136
- throw Error(`Could not fetch Whirlpool data for ${pool.toString()}`);
4140
+ async getOrcaPoolPrice(pool, tokenADecimals, tokenBDecimals) {
4141
+ // if the decimals are provided read from API, otherwise use RPC
4142
+ if (tokenADecimals && tokenBDecimals) {
4143
+ const whirlpool = await accounts_2.Whirlpool.fetch(this._rpc, pool, this._orcaService.getWhirlpoolProgramId());
4144
+ if (!whirlpool) {
4145
+ throw Error(`Could not fetch Whirlpool data for ${pool.toString()}`);
4146
+ }
4147
+ return new decimal_js_1.default((0, whirlpools_core_1.sqrtPriceToPrice)(BigInt(whirlpool.sqrtPrice.toString()), tokenADecimals, tokenBDecimals));
4148
+ }
4149
+ else {
4150
+ const whirlpool = await this._orcaService.getOrcaWhirlpool(pool);
4151
+ if (!whirlpool) {
4152
+ throw Error(`Could not fetch Whirlpool data for ${pool.toString()}`);
4153
+ }
4154
+ return new decimal_js_1.default((0, whirlpools_core_1.sqrtPriceToPrice)(BigInt(whirlpool.sqrtPrice.toString()), whirlpool.tokenA.decimals, whirlpool.tokenB.decimals));
4137
4155
  }
4138
- return poolData.price;
4139
4156
  }
4140
4157
  async getRaydiumPoolPrice(pool) {
4141
4158
  const poolState = await accounts_3.PoolState.fetch(this._rpc, pool, this._raydiumService.getRaydiumProgramId());
@@ -4200,7 +4217,9 @@ class Kamino {
4200
4217
  this._cluster === 'devnet') {
4201
4218
  return await this._rpc
4202
4219
  .getProgramAccounts(address_lookup_table_1.ADDRESS_LOOKUP_TABLE_PROGRAM_ADDRESS, {
4203
- filters: [{ memcmp: { offset: 22n, bytes: pubkeys_1.LUT_OWNER_KEY, encoding: 'base58' } }],
4220
+ filters: [
4221
+ { memcmp: { offset: 22n, bytes: pubkeys_1.LUT_OWNER_KEY.toString(), encoding: 'base58' } },
4222
+ ],
4204
4223
  dataSlice: { length: 0, offset: 0 },
4205
4224
  })
4206
4225
  .send()
@@ -4483,7 +4502,7 @@ class Kamino {
4483
4502
  if (isOrca) {
4484
4503
  const prices = await this.getAllPrices();
4485
4504
  const collateralInfos = await this.getCollateralInfos();
4486
- return this._orcaService.getStrategyWhirlpoolPoolAprApy(strategyState, collateralInfos, prices, orcaPools);
4505
+ return this._orcaService.getStrategyWhirlpoolPoolAprApy(strategyState, collateralInfos, prices);
4487
4506
  }
4488
4507
  if (isRaydium) {
4489
4508
  return this._raydiumService.getStrategyWhirlpoolPoolAprApy(strategyState, raydiumPools);
@@ -4658,23 +4677,15 @@ class Kamino {
4658
4677
  const tokenMintB = whirlpoolState.tokenMintB;
4659
4678
  const decimalsA = await (0, utils_1.getMintDecimals)(this._rpc, tokenMintA);
4660
4679
  const decimalsB = await (0, utils_1.getMintDecimals)(this._rpc, tokenMintB);
4661
- const tickLowerIndex = (0, whirlpool_sdk_1.getNearestValidTickIndexFromTickIndex)((0, whirlpool_sdk_1.priceToTickIndex)(lowerPrice, decimalsA, decimalsB), whirlpoolState.tickSpacing);
4662
- const tickUpperIndex = (0, whirlpool_sdk_1.getNearestValidTickIndexFromTickIndex)((0, whirlpool_sdk_1.priceToTickIndex)(upperPrice, decimalsA, decimalsB), whirlpoolState.tickSpacing);
4663
- const params = {
4664
- tokenMintA: (0, compat_2.toLegacyPublicKey)(tokenMintA),
4665
- tokenMintB: (0, compat_2.toLegacyPublicKey)(tokenMintB),
4666
- tickCurrentIndex: whirlpoolState.tickCurrentIndex,
4667
- sqrtPrice: whirlpoolState.sqrtPrice,
4668
- inputTokenMint: (0, compat_2.toLegacyPublicKey)(tokenMintA),
4669
- inputTokenAmount: new bn_js_1.default((0, utils_1.collToLamportsDecimal)(tokenAAmountToDeposit, decimalsA).toString()),
4670
- tickLowerIndex,
4671
- tickUpperIndex,
4672
- slippageTolerance: whirlpool_sdk_1.defaultSlippagePercentage,
4680
+ const tickLowerIndex = (0, utils_1.getNearestValidTickIndexFromTickIndex)((0, whirlpools_core_1.priceToTickIndex)(lowerPrice.toNumber(), decimalsA, decimalsB), whirlpoolState.tickSpacing);
4681
+ const tickUpperIndex = (0, utils_1.getNearestValidTickIndexFromTickIndex)((0, whirlpools_core_1.priceToTickIndex)(upperPrice.toNumber(), decimalsA, decimalsB), whirlpoolState.tickSpacing);
4682
+ const param = {
4683
+ tokenA: BigInt((0, utils_1.collToLamportsDecimal)(tokenAAmountToDeposit, decimalsA).toString()),
4673
4684
  };
4674
- const addLiqResult = (0, add_liquidity_1.getAddLiquidityQuote)(params);
4685
+ const addLiqResult = (0, utils_1.getIncreaseLiquidityQuote)(param, whirlpoolState, tickLowerIndex, tickUpperIndex, utils_1.defaultSlippagePercentageBPS, undefined, undefined);
4675
4686
  return [
4676
- (0, utils_1.lamportsToNumberDecimal)(addLiqResult.estTokenA.toNumber(), decimalsA),
4677
- (0, utils_1.lamportsToNumberDecimal)(addLiqResult.estTokenB.toNumber(), decimalsB),
4687
+ (0, utils_1.lamportsToNumberDecimal)(new decimal_js_1.default(addLiqResult.tokenEstA.toString()), decimalsA),
4688
+ (0, utils_1.lamportsToNumberDecimal)(new decimal_js_1.default(addLiqResult.tokenEstB.toString()), decimalsB),
4678
4689
  ];
4679
4690
  }
4680
4691
  else if (dex === 'METEORA') {
@@ -4771,9 +4782,7 @@ class Kamino {
4771
4782
  throw new Error(`Unable to get Orca whirlpool for pubkey ${strategyState.pool}`);
4772
4783
  }
4773
4784
  return this.calculateAmountsOrca({
4774
- whirlpoolConfig: whirlpool.whirlpoolsConfig,
4775
- tokenAMint: strategyState.tokenAMint,
4776
- tokenBMint: strategyState.tokenBMint,
4785
+ whirlpoolState: whirlpool,
4777
4786
  positionAddress: strategyState.position,
4778
4787
  tokenAAmount,
4779
4788
  tokenBAmount,
@@ -4789,46 +4798,42 @@ class Kamino {
4789
4798
  throw new Error(`The strategy ${strategy.toString()} is not Orca or Raydium`);
4790
4799
  }
4791
4800
  };
4792
- calculateAmountsOrca = async ({ whirlpoolConfig, tokenAMint, tokenBMint, positionAddress, tokenAAmount, tokenBAmount, }) => {
4801
+ calculateAmountsOrca = async ({ whirlpoolState, positionAddress, tokenAAmount, tokenBAmount, }) => {
4793
4802
  if (!tokenAAmount && !tokenBAmount) {
4794
4803
  return [new decimal_js_1.default(0), new decimal_js_1.default(0)];
4795
4804
  }
4796
4805
  // Given A in ATA, calc how much A and B
4797
- const accessor = new orca_dal_1.OrcaDAL(whirlpoolConfig, this._orcaService.getWhirlpoolProgramId(), this._legacyConnection);
4798
- const orcaPosition = new orca_position_1.OrcaPosition(accessor);
4799
- const defaultSlippagePercentage = whirlpool_sdk_1.Percentage.fromFraction(1, 1000); // 0.1%
4800
- const primaryTokenAmount = tokenAAmount || tokenBAmount;
4801
- const primaryTokenMint = tokenAAmount ? tokenAMint : tokenBMint;
4802
- const secondaryTokenAmount = tokenAAmount ? tokenBAmount : tokenAAmount;
4803
- const secondaryTokenMint = tokenAAmount ? tokenBMint : tokenAMint;
4804
- let params = {
4805
- positionAddress,
4806
- tokenMint: primaryTokenMint,
4807
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
4808
- tokenAmount: new bn_js_1.default(primaryTokenAmount.toString()), // safe to use ! here because we check in the beginning that at least one of the amounts are not undefined;
4809
- refresh: true,
4810
- slippageTolerance: defaultSlippagePercentage,
4811
- };
4812
- const estimatedGivenPrimary = await orcaPosition.getAddLiquidityQuote(params);
4813
- if (secondaryTokenAmount &&
4814
- new decimal_js_1.default(estimatedGivenPrimary.estTokenB.toString()) > new decimal_js_1.default(secondaryTokenAmount.toString())) {
4815
- params = {
4816
- positionAddress,
4817
- tokenMint: secondaryTokenMint,
4818
- tokenAmount: new bn_js_1.default(secondaryTokenAmount.toString()),
4819
- refresh: true,
4820
- slippageTolerance: defaultSlippagePercentage,
4806
+ const defaultSlippagePercentageBPS = 10;
4807
+ const positionState = await accounts_2.Position.fetch(this._rpc, positionAddress, this._orcaService.getWhirlpoolProgramId());
4808
+ if (!positionState) {
4809
+ throw new Error(`Unable to get Orca position for pubkey ${positionAddress}`);
4810
+ }
4811
+ let computedAmounts = [new decimal_js_1.default(0), new decimal_js_1.default(0)];
4812
+ if (tokenAAmount) {
4813
+ const tokenAForQuote = BigInt(tokenAAmount.toString());
4814
+ const params = {
4815
+ tokenA: tokenAForQuote,
4821
4816
  };
4822
- const estimatedGivenSecondary = await orcaPosition.getAddLiquidityQuote(params);
4823
- return [
4824
- new decimal_js_1.default(estimatedGivenSecondary.estTokenA.toString()),
4825
- new decimal_js_1.default(estimatedGivenSecondary.estTokenB.toString()),
4817
+ const estimatedGivenA = (0, utils_1.getIncreaseLiquidityQuote)(params, whirlpoolState, positionState.tickLowerIndex, positionState.tickUpperIndex, defaultSlippagePercentageBPS, undefined, // todo: use new Wirlpool state and read transfer fees
4818
+ undefined);
4819
+ computedAmounts = [
4820
+ new decimal_js_1.default(estimatedGivenA.tokenEstA.toString()),
4821
+ new decimal_js_1.default(estimatedGivenA.tokenEstB.toString()),
4826
4822
  ];
4827
4823
  }
4828
- return [
4829
- new decimal_js_1.default(estimatedGivenPrimary.estTokenA.toString()),
4830
- new decimal_js_1.default(estimatedGivenPrimary.estTokenB.toString()),
4831
- ];
4824
+ if (tokenBAmount && computedAmounts[1] > tokenBAmount) {
4825
+ const tokenBForQuote = BigInt(tokenBAmount.toString());
4826
+ const params = {
4827
+ tokenB: tokenBForQuote,
4828
+ };
4829
+ const estimatedGivenB = (0, utils_1.getIncreaseLiquidityQuote)(params, whirlpoolState, positionState.tickLowerIndex, positionState.tickUpperIndex, defaultSlippagePercentageBPS, undefined, // todo: use new Wirlpool state and read transfer fees
4830
+ undefined);
4831
+ computedAmounts = [
4832
+ new decimal_js_1.default(estimatedGivenB.tokenEstA.toString()),
4833
+ new decimal_js_1.default(estimatedGivenB.tokenEstB.toString()),
4834
+ ];
4835
+ }
4836
+ return computedAmounts;
4832
4837
  };
4833
4838
  calculateAmountsRaydium = async ({ strategyState, tokenAAmount, tokenBAmount, }) => {
4834
4839
  if (!tokenAAmount && !tokenBAmount) {
@@ -5008,18 +5013,10 @@ class Kamino {
5008
5013
  throw new Error(`Whirlpool position ${strategyState.position} does not exist`);
5009
5014
  }
5010
5015
  const params = {
5011
- tokenMintA: (0, compat_2.toLegacyPublicKey)(strategyState.tokenAMint),
5012
- tokenMintB: (0, compat_2.toLegacyPublicKey)(strategyState.tokenBMint),
5013
- tickCurrentIndex: whirlpool.tickCurrentIndex,
5014
- sqrtPrice: whirlpool.sqrtPrice,
5015
- inputTokenMint: (0, compat_2.toLegacyPublicKey)(strategyState.tokenAMint),
5016
- inputTokenAmount: amountA,
5017
- tickLowerIndex: position.tickLowerIndex,
5018
- tickUpperIndex: position.tickUpperIndex,
5019
- slippageTolerance: whirlpool_sdk_1.defaultSlippagePercentage,
5016
+ tokenA: BigInt(amountA.toString()),
5020
5017
  };
5021
- const quote = (0, add_liquidity_1.getAddLiquidityQuote)(params);
5022
- return { amountSlippageA: quote.estTokenA, amountSlippageB: quote.estTokenB };
5018
+ const quote = (0, utils_1.getIncreaseLiquidityQuote)(params, whirlpool, position.tickLowerIndex, position.tickUpperIndex, utils_1.defaultSlippagePercentageBPS, undefined, undefined);
5019
+ return { amountSlippageA: new bn_js_1.default(quote.tokenEstA.toString()), amountSlippageB: new bn_js_1.default(quote.tokenEstB.toString()) };
5023
5020
  }
5024
5021
  async getDepositRatioFromAMeteora(strategy) {
5025
5022
  const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);
@@ -5029,7 +5026,7 @@ class Kamino {
5029
5026
  if (!poolState) {
5030
5027
  throw Error(`Could not fetch lb pair state with pubkey ${strategyState.pool.toString()}`);
5031
5028
  }
5032
- return { amountSlippageA: utils_1.ZERO_BN, amountSlippageB: utils_1.ZERO_BN };
5029
+ return { amountSlippageA: constants_1.ZERO_BN, amountSlippageB: constants_1.ZERO_BN };
5033
5030
  }
5034
5031
  async getDepositRatioFromBMeteora(strategy) {
5035
5032
  const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);
@@ -5040,7 +5037,7 @@ class Kamino {
5040
5037
  if (!poolState) {
5041
5038
  throw Error(`Could not fetch lb pair state with pubkey ${strategyState.pool.toString()}`);
5042
5039
  }
5043
- return { amountSlippageA: utils_1.ZERO_BN, amountSlippageB: utils_1.ZERO_BN };
5040
+ return { amountSlippageA: constants_1.ZERO_BN, amountSlippageB: constants_1.ZERO_BN };
5044
5041
  }
5045
5042
  getDepositRatioFromBOrca = async (strategy, amountB) => {
5046
5043
  const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);
@@ -5052,19 +5049,11 @@ class Kamino {
5052
5049
  if (!position) {
5053
5050
  throw new Error(`Whirlpool position ${strategyState.position} does not exist`);
5054
5051
  }
5055
- const params = {
5056
- tokenMintA: (0, compat_2.toLegacyPublicKey)(strategyState.tokenAMint),
5057
- tokenMintB: (0, compat_2.toLegacyPublicKey)(strategyState.tokenBMint),
5058
- tickCurrentIndex: whirlpool.tickCurrentIndex,
5059
- sqrtPrice: whirlpool.sqrtPrice,
5060
- inputTokenMint: (0, compat_2.toLegacyPublicKey)(strategyState.tokenBMint),
5061
- inputTokenAmount: amountB,
5062
- tickLowerIndex: position.tickLowerIndex,
5063
- tickUpperIndex: position.tickUpperIndex,
5064
- slippageTolerance: whirlpool_sdk_1.defaultSlippagePercentage,
5052
+ const param = {
5053
+ tokenB: BigInt(amountB.toString()),
5065
5054
  };
5066
- const quote = (0, add_liquidity_1.getAddLiquidityQuote)(params);
5067
- return { amountSlippageA: quote.estTokenA, amountSlippageB: quote.estTokenB };
5055
+ const quote = (0, utils_1.getIncreaseLiquidityQuote)(param, whirlpool, position.tickLowerIndex, position.tickUpperIndex, utils_1.defaultSlippagePercentageBPS, undefined, undefined);
5056
+ return { amountSlippageA: new bn_js_1.default(quote.tokenEstA.toString()), amountSlippageB: new bn_js_1.default(quote.tokenEstB.toString()) };
5068
5057
  };
5069
5058
  getDepositRatioFromARaydium = async (strategy, amountA) => {
5070
5059
  const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);
@@ -5278,8 +5267,8 @@ class Kamino {
5278
5267
  const { address: poolAddress, whirlpool: whilrpoolState } = await this.getWhirlpoolStateIfNotFetched(pool);
5279
5268
  const decimalsA = await (0, utils_1.getMintDecimals)(this._rpc, whilrpoolState.tokenMintA);
5280
5269
  const decimalsB = await (0, utils_1.getMintDecimals)(this._rpc, whilrpoolState.tokenMintB);
5281
- const tickIndex = (0, whirlpool_sdk_1.getNextValidTickIndex)((0, whirlpool_sdk_1.priceToTickIndex)(price, decimalsA, decimalsB), whilrpoolState.tickSpacing);
5282
- const startTickIndex = (0, whirlpool_sdk_1.getStartTickIndex)(tickIndex, whilrpoolState.tickSpacing);
5270
+ const tickIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)((0, whirlpools_core_1.priceToTickIndex)(price.toNumber(), decimalsA, decimalsB), whilrpoolState.tickSpacing);
5271
+ const startTickIndex = (0, whirlpools_core_1.getTickArrayStartTickIndex)(tickIndex, whilrpoolState.tickSpacing);
5283
5272
  const [startTickIndexPk, _startTickIndexBump] = await (0, utils_1.getTickArray)(this._orcaService.getWhirlpoolProgramId(), poolAddress, startTickIndex);
5284
5273
  const tick = await accounts_2.TickArray.fetch(this._rpc, startTickIndexPk, this._orcaService.getWhirlpoolProgramId());
5285
5274
  // initialize tick if it doesn't exist