@kamino-finance/kliquidity-sdk 8.3.1 → 8.3.2
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/Kamino.d.ts +12 -12
- package/dist/Kamino.d.ts.map +1 -1
- package/dist/Kamino.js +101 -120
- package/dist/Kamino.js.map +1 -1
- package/dist/constants/numericalValues.d.ts +3 -0
- package/dist/constants/numericalValues.d.ts.map +1 -1
- package/dist/constants/numericalValues.js +4 -1
- package/dist/constants/numericalValues.js.map +1 -1
- package/dist/rebalance_methods/autodriftRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/autodriftRebalance.js +10 -10
- package/dist/rebalance_methods/autodriftRebalance.js.map +1 -1
- package/dist/rebalance_methods/driftRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/driftRebalance.js +10 -10
- package/dist/rebalance_methods/driftRebalance.js.map +1 -1
- package/dist/rebalance_methods/expanderRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/expanderRebalance.js +3 -4
- package/dist/rebalance_methods/expanderRebalance.js.map +1 -1
- package/dist/rebalance_methods/pricePercentageRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/pricePercentageRebalance.js +5 -6
- package/dist/rebalance_methods/pricePercentageRebalance.js.map +1 -1
- package/dist/rebalance_methods/pricePercentageWithResetRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/pricePercentageWithResetRebalance.js +5 -6
- package/dist/rebalance_methods/pricePercentageWithResetRebalance.js.map +1 -1
- package/dist/rebalance_methods/takeProfitRebalance.d.ts.map +1 -1
- package/dist/rebalance_methods/takeProfitRebalance.js +5 -5
- package/dist/rebalance_methods/takeProfitRebalance.js.map +1 -1
- package/dist/services/OrcaService.d.ts +7 -11
- package/dist/services/OrcaService.d.ts.map +1 -1
- package/dist/services/OrcaService.js +132 -100
- package/dist/services/OrcaService.js.map +1 -1
- package/dist/services/OrcaWhirlpoolsResponse.d.ts +63 -92
- package/dist/services/OrcaWhirlpoolsResponse.d.ts.map +1 -1
- package/dist/utils/farms.d.ts +1 -0
- package/dist/utils/farms.d.ts.map +1 -0
- package/dist/utils/farms.js +2 -0
- package/dist/utils/farms.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/orca.d.ts +37 -1
- package/dist/utils/orca.d.ts.map +1 -1
- package/dist/utils/orca.js +242 -0
- package/dist/utils/orca.js.map +1 -1
- package/dist/utils/tokenUtils.d.ts +5 -5
- package/dist/utils/tokenUtils.d.ts.map +1 -1
- package/dist/utils/tokenUtils.js +11 -7
- package/dist/utils/tokenUtils.js.map +1 -1
- package/dist/utils/types.d.ts +5 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/dist/utils/types.js.map +1 -1
- package/dist/utils/utils.d.ts +0 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +3 -4
- package/dist/utils/utils.js.map +1 -1
- package/dist/utils/whirlpools.d.ts +12 -1
- package/dist/utils/whirlpools.d.ts.map +1 -1
- package/dist/utils/whirlpools.js +30 -29
- package/dist/utils/whirlpools.js.map +1 -1
- package/package.json +4 -3
- package/src/Kamino.ts +252 -205
- package/src/constants/numericalValues.ts +5 -0
- package/src/rebalance_methods/autodriftRebalance.ts +30 -22
- package/src/rebalance_methods/driftRebalance.ts +30 -22
- package/src/rebalance_methods/expanderRebalance.ts +7 -4
- package/src/rebalance_methods/pricePercentageRebalance.ts +13 -6
- package/src/rebalance_methods/pricePercentageWithResetRebalance.ts +13 -6
- package/src/rebalance_methods/takeProfitRebalance.ts +13 -5
- package/src/services/OrcaService.ts +162 -125
- package/src/services/OrcaWhirlpoolsResponse.ts +69 -101
- package/src/utils/farms.ts +0 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/orca.ts +377 -1
- package/src/utils/tokenUtils.ts +5 -5
- package/src/utils/types.ts +7 -0
- package/src/utils/utils.ts +2 -4
- package/src/utils/whirlpools.ts +50 -31
package/src/Kamino.ts
CHANGED
|
@@ -30,21 +30,15 @@ import {
|
|
|
30
30
|
InitializeTickArrayAccounts,
|
|
31
31
|
InitializeTickArrayArgs,
|
|
32
32
|
} from './@codegen/whirlpools/instructions';
|
|
33
|
-
import { Position, TickArray, Whirlpool } from './@codegen/whirlpools/accounts';
|
|
33
|
+
import { Position as OrcaPosition, TickArray, Whirlpool } from './@codegen/whirlpools/accounts';
|
|
34
34
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
priceToTickIndex,
|
|
43
|
-
sqrtPriceX64ToPrice,
|
|
44
|
-
tickIndexToPrice,
|
|
45
|
-
} from '@orca-so/whirlpool-sdk';
|
|
46
|
-
import { OrcaDAL } from '@orca-so/whirlpool-sdk/dist/dal/orca-dal';
|
|
47
|
-
import { OrcaPosition } from '@orca-so/whirlpool-sdk/dist/position/orca-position';
|
|
35
|
+
sqrtPriceToPrice as orcaSqrtPriceToPrice,
|
|
36
|
+
getTickArrayStartTickIndex as orcaGetTickArrayStartTickIndex,
|
|
37
|
+
priceToTickIndex as orcaPriceToTickIndex,
|
|
38
|
+
IncreaseLiquidityQuote,
|
|
39
|
+
sqrtPriceToPrice,
|
|
40
|
+
tickIndexToPrice as orcaTickIndexToPrice,
|
|
41
|
+
} from '@orca-so/whirlpools-core';
|
|
48
42
|
import {
|
|
49
43
|
getEmptyShareData,
|
|
50
44
|
Holdings,
|
|
@@ -119,7 +113,9 @@ import {
|
|
|
119
113
|
WithdrawAllAndCloseIxns,
|
|
120
114
|
WithdrawShares,
|
|
121
115
|
ZERO,
|
|
122
|
-
|
|
116
|
+
getNearestValidTickIndexFromTickIndex as orcaGetNearestValidTickIndexFromTickIndex,
|
|
117
|
+
getIncreaseLiquidityQuote,
|
|
118
|
+
defaultSlippagePercentageBPS,
|
|
123
119
|
} from './utils';
|
|
124
120
|
import {
|
|
125
121
|
checkExpectedVaultsBalances,
|
|
@@ -165,7 +161,7 @@ import {
|
|
|
165
161
|
import BN from 'bn.js';
|
|
166
162
|
import StrategyWithAddress from './models/StrategyWithAddress';
|
|
167
163
|
import { Rebalancing, Uninitialized } from './@codegen/kliquidity/types/StrategyStatus';
|
|
168
|
-
import { FRONTEND_KAMINO_STRATEGY_URL, METADATA_PROGRAM_ID, U64_MAX } from './constants';
|
|
164
|
+
import { FRONTEND_KAMINO_STRATEGY_URL, METADATA_PROGRAM_ID, U64_MAX, ZERO_BN } from './constants';
|
|
169
165
|
import {
|
|
170
166
|
CollateralInfo,
|
|
171
167
|
ExecutiveWithdrawActionKind,
|
|
@@ -177,12 +173,7 @@ import {
|
|
|
177
173
|
} from './@codegen/kliquidity/types';
|
|
178
174
|
import { AmmConfig, PersonalPositionState, PoolState } from './@codegen/raydium/accounts';
|
|
179
175
|
|
|
180
|
-
import { OrcaService, RaydiumService, Whirlpool as
|
|
181
|
-
import {
|
|
182
|
-
getAddLiquidityQuote,
|
|
183
|
-
InternalAddLiquidityQuote,
|
|
184
|
-
InternalAddLiquidityQuoteParam,
|
|
185
|
-
} from '@orca-so/whirlpool-sdk/dist/position/quotes/add-liquidity';
|
|
176
|
+
import { OrcaService, RaydiumService, Whirlpool as WhirlpoolAPIResponse, WhirlpoolAprApy } from './services';
|
|
186
177
|
import { Pool } from './services/RaydiumPoolsResponse';
|
|
187
178
|
import {
|
|
188
179
|
UpdateCollectFeesFee,
|
|
@@ -327,10 +318,10 @@ import {
|
|
|
327
318
|
import {
|
|
328
319
|
getPdaProtocolPositionAddress,
|
|
329
320
|
i32ToBytes,
|
|
330
|
-
LiquidityMath,
|
|
331
|
-
SqrtPriceMath,
|
|
332
|
-
TickMath,
|
|
333
|
-
TickUtils,
|
|
321
|
+
LiquidityMath as RaydiumLiquidityMath,
|
|
322
|
+
SqrtPriceMath as RaydiumSqrtPriceMath,
|
|
323
|
+
TickMath as RaydiumTickMath,
|
|
324
|
+
TickUtils as RaydiumTickUtils,
|
|
334
325
|
} from '@raydium-io/raydium-sdk-v2/lib';
|
|
335
326
|
import {
|
|
336
327
|
ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
@@ -355,6 +346,7 @@ import { fetchMultipleLookupTableAccounts } from './utils/lookupTable';
|
|
|
355
346
|
import type { AccountInfoBase, AccountInfoWithJsonData, AccountInfoWithPubkey } from '@solana/rpc-types';
|
|
356
347
|
import { Connection } from '@solana/web3.js';
|
|
357
348
|
import { toLegacyPublicKey } from './utils/compat';
|
|
349
|
+
import { IncreaseLiquidityQuoteParam } from '@orca-so/whirlpools';
|
|
358
350
|
|
|
359
351
|
const addressEncoder = getAddressEncoder();
|
|
360
352
|
|
|
@@ -408,7 +400,7 @@ export class Kamino {
|
|
|
408
400
|
}
|
|
409
401
|
|
|
410
402
|
this._scope = new Scope(cluster, rpc);
|
|
411
|
-
this._orcaService = new OrcaService(rpc, legacyConnection,
|
|
403
|
+
this._orcaService = new OrcaService(rpc, legacyConnection, whirlpoolProgramId);
|
|
412
404
|
this._raydiumService = new RaydiumService(rpc, legacyConnection, raydiumProgramId);
|
|
413
405
|
this._meteoraService = new MeteoraService(rpc, meteoraProgramId);
|
|
414
406
|
|
|
@@ -419,6 +411,8 @@ export class Kamino {
|
|
|
419
411
|
|
|
420
412
|
getConnection = () => this._rpc;
|
|
421
413
|
|
|
414
|
+
getLegacyConnection = () => this._legacyConnection;
|
|
415
|
+
|
|
422
416
|
getProgramID = () => this._kliquidityProgramId;
|
|
423
417
|
|
|
424
418
|
setGlobalConfig = (globalConfig: Address) => {
|
|
@@ -962,7 +956,7 @@ export class Kamino {
|
|
|
962
956
|
if (pools.length === 0) {
|
|
963
957
|
throw new Error(`No pool found for ${poolTokenA.toString()} and ${poolTokenB.toString()}`);
|
|
964
958
|
}
|
|
965
|
-
return pools[0].price;
|
|
959
|
+
return Number(pools[0].price);
|
|
966
960
|
} else if (dex === 'RAYDIUM') {
|
|
967
961
|
const pools = await this.getRaydiumPoolsForTokens(poolTokenA, poolTokenB);
|
|
968
962
|
if (pools.length === 0) {
|
|
@@ -1033,7 +1027,7 @@ export class Kamino {
|
|
|
1033
1027
|
let pool: Address = DEFAULT_PUBLIC_KEY;
|
|
1034
1028
|
const orcaPools = await this.getOrcaPoolsForTokens(poolTokenA, poolTokenB);
|
|
1035
1029
|
orcaPools.forEach((element) => {
|
|
1036
|
-
if (element.
|
|
1030
|
+
if (element.feeRate * FullBPS === feeBPS.toNumber()) {
|
|
1037
1031
|
pool = address(element.address);
|
|
1038
1032
|
}
|
|
1039
1033
|
});
|
|
@@ -1080,22 +1074,24 @@ export class Kamino {
|
|
|
1080
1074
|
if (dex === 'ORCA') {
|
|
1081
1075
|
const pools = await this.getOrcaPoolsForTokens(tokenMintA, tokenMintB);
|
|
1082
1076
|
const genericPoolInfos: GenericPoolInfo[] = await Promise.all(
|
|
1083
|
-
pools.map(async (pool:
|
|
1077
|
+
pools.map(async (pool: WhirlpoolAPIResponse) => {
|
|
1084
1078
|
const positionsCount = new Decimal(await this.getPositionsCountForPool(dex, address(pool.address)));
|
|
1085
1079
|
// read price from pool
|
|
1086
|
-
const poolData = await this._orcaService.
|
|
1080
|
+
const poolData = await this._orcaService.getOrcaWhirlpool(address(pool.address));
|
|
1087
1081
|
if (!poolData) {
|
|
1088
1082
|
throw new Error(`Pool ${pool.address} not found`);
|
|
1089
1083
|
}
|
|
1090
1084
|
const poolInfo: GenericPoolInfo = {
|
|
1091
1085
|
dex,
|
|
1092
1086
|
address: address(pool.address),
|
|
1093
|
-
price:
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1087
|
+
price: new Decimal(
|
|
1088
|
+
orcaSqrtPriceToPrice(BigInt(poolData.sqrtPrice), pool.tokenA.decimals, pool.tokenB.decimals)
|
|
1089
|
+
),
|
|
1090
|
+
tokenMintA: address(pool.tokenMintA),
|
|
1091
|
+
tokenMintB: address(pool.tokenMintB),
|
|
1092
|
+
tvl: pool.tvlUsdc ? new Decimal(pool.tvlUsdc) : undefined,
|
|
1093
|
+
feeRate: new Decimal(pool.feeRate).mul(FullBPS),
|
|
1094
|
+
volumeOnLast7d: pool.stats['7d'] ? new Decimal(pool.stats['7d'].volume) : undefined,
|
|
1099
1095
|
tickSpacing: new Decimal(pool.tickSpacing),
|
|
1100
1096
|
positions: positionsCount,
|
|
1101
1097
|
};
|
|
@@ -1157,15 +1153,15 @@ export class Kamino {
|
|
|
1157
1153
|
}
|
|
1158
1154
|
}
|
|
1159
1155
|
|
|
1160
|
-
getOrcaPoolsForTokens = async (poolTokenA: Address, poolTokenB: Address): Promise<
|
|
1161
|
-
const pools:
|
|
1156
|
+
getOrcaPoolsForTokens = async (poolTokenA: Address, poolTokenB: Address): Promise<WhirlpoolAPIResponse[]> => {
|
|
1157
|
+
const pools: WhirlpoolAPIResponse[] = [];
|
|
1162
1158
|
const poolTokenAString = poolTokenA.toString();
|
|
1163
1159
|
const poolTokenBString = poolTokenB.toString();
|
|
1164
1160
|
const whirlpools = await this._orcaService.getOrcaWhirlpools();
|
|
1165
|
-
whirlpools.
|
|
1161
|
+
whirlpools.forEach((element) => {
|
|
1166
1162
|
if (
|
|
1167
|
-
(element.
|
|
1168
|
-
(element.
|
|
1163
|
+
(element.tokenMintA === poolTokenAString && element.tokenMintB === poolTokenBString) ||
|
|
1164
|
+
(element.tokenMintA === poolTokenBString && element.tokenMintB === poolTokenAString)
|
|
1169
1165
|
)
|
|
1170
1166
|
pools.push(element);
|
|
1171
1167
|
});
|
|
@@ -1484,7 +1480,7 @@ export class Kamino {
|
|
|
1484
1480
|
);
|
|
1485
1481
|
|
|
1486
1482
|
fetchBalances.push(
|
|
1487
|
-
...this.getBalance<Whirlpool,
|
|
1483
|
+
...this.getBalance<Whirlpool, OrcaPosition>(
|
|
1488
1484
|
orcaStrategies,
|
|
1489
1485
|
orcaPools,
|
|
1490
1486
|
orcaPositions,
|
|
@@ -1602,18 +1598,18 @@ export class Kamino {
|
|
|
1602
1598
|
const decimalsA = strategy.tokenAMintDecimals.toNumber();
|
|
1603
1599
|
const decimalsB = strategy.tokenBMintDecimals.toNumber();
|
|
1604
1600
|
|
|
1605
|
-
const poolPrice =
|
|
1601
|
+
const poolPrice = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(pool.sqrtPriceX64, decimalsA, decimalsB);
|
|
1606
1602
|
const twapPrice =
|
|
1607
1603
|
strategyPrices.aTwapPrice !== null && strategyPrices.bTwapPrice !== null
|
|
1608
1604
|
? strategyPrices.aTwapPrice.div(strategyPrices.bTwapPrice)
|
|
1609
1605
|
: null;
|
|
1610
|
-
const upperPrice =
|
|
1611
|
-
|
|
1606
|
+
const upperPrice = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(
|
|
1607
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex),
|
|
1612
1608
|
decimalsA,
|
|
1613
1609
|
decimalsB
|
|
1614
1610
|
);
|
|
1615
|
-
const lowerPrice =
|
|
1616
|
-
|
|
1611
|
+
const lowerPrice = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(
|
|
1612
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex),
|
|
1617
1613
|
decimalsA,
|
|
1618
1614
|
decimalsB
|
|
1619
1615
|
);
|
|
@@ -1726,10 +1722,10 @@ export class Kamino {
|
|
|
1726
1722
|
position: PersonalPositionState,
|
|
1727
1723
|
mode: 'DEPOSIT' | 'WITHDRAW' = 'WITHDRAW'
|
|
1728
1724
|
): TokenHoldings => {
|
|
1729
|
-
const lowerSqrtPriceX64 =
|
|
1730
|
-
const upperSqrtPriceX64 =
|
|
1725
|
+
const lowerSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex);
|
|
1726
|
+
const upperSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex);
|
|
1731
1727
|
|
|
1732
|
-
const { amountA, amountB } =
|
|
1728
|
+
const { amountA, amountB } = RaydiumLiquidityMath.getAmountsFromLiquidity(
|
|
1733
1729
|
pool.sqrtPriceX64,
|
|
1734
1730
|
new BN(lowerSqrtPriceX64),
|
|
1735
1731
|
new BN(upperSqrtPriceX64),
|
|
@@ -1790,7 +1786,7 @@ export class Kamino {
|
|
|
1790
1786
|
private getOrcaBalances = async (
|
|
1791
1787
|
strategy: WhirlpoolStrategy,
|
|
1792
1788
|
pool: Whirlpool,
|
|
1793
|
-
position:
|
|
1789
|
+
position: OrcaPosition,
|
|
1794
1790
|
collateralInfos: CollateralInfo[],
|
|
1795
1791
|
prices?: OraclePrices,
|
|
1796
1792
|
disabledTokensPrices?: Map<Address, Decimal>,
|
|
@@ -1814,13 +1810,13 @@ export class Kamino {
|
|
|
1814
1810
|
const decimalsA = strategy.tokenAMintDecimals.toNumber();
|
|
1815
1811
|
const decimalsB = strategy.tokenBMintDecimals.toNumber();
|
|
1816
1812
|
|
|
1817
|
-
const poolPrice =
|
|
1813
|
+
const poolPrice = new Decimal(orcaSqrtPriceToPrice(BigInt(pool.sqrtPrice.toString()), decimalsA, decimalsB));
|
|
1818
1814
|
const twapPrice =
|
|
1819
1815
|
strategyPrices.aTwapPrice !== null && strategyPrices.bTwapPrice !== null
|
|
1820
1816
|
? strategyPrices.aTwapPrice.div(strategyPrices.bTwapPrice)
|
|
1821
1817
|
: null;
|
|
1822
|
-
const upperPrice =
|
|
1823
|
-
const lowerPrice =
|
|
1818
|
+
const upperPrice = new Decimal(orcaTickIndexToPrice(position.tickUpperIndex, decimalsA, decimalsB));
|
|
1819
|
+
const lowerPrice = new Decimal(orcaTickIndexToPrice(position.tickLowerIndex, decimalsA, decimalsB));
|
|
1824
1820
|
let lowerResetPrice: Decimal | null = null;
|
|
1825
1821
|
let upperResetPrice: Decimal | null = null;
|
|
1826
1822
|
const dex = numberToDex(strategy.strategyDex.toNumber());
|
|
@@ -1856,14 +1852,14 @@ export class Kamino {
|
|
|
1856
1852
|
private getOrcaTokensBalances = (
|
|
1857
1853
|
strategy: WhirlpoolStrategy,
|
|
1858
1854
|
pool: Whirlpool,
|
|
1859
|
-
position:
|
|
1855
|
+
position: OrcaPosition,
|
|
1860
1856
|
mode: 'DEPOSIT' | 'WITHDRAW' = 'WITHDRAW'
|
|
1861
1857
|
): TokenHoldings => {
|
|
1862
1858
|
const quote = getRemoveLiquidityQuote(
|
|
1863
1859
|
{
|
|
1864
1860
|
positionAddress: strategy.position,
|
|
1865
1861
|
liquidity: position.liquidity,
|
|
1866
|
-
slippageTolerance:
|
|
1862
|
+
slippageTolerance: { numerator: ZERO_BN, denominator: new BN(1000) },
|
|
1867
1863
|
sqrtPrice: pool.sqrtPrice,
|
|
1868
1864
|
tickLowerIndex: position.tickLowerIndex,
|
|
1869
1865
|
tickUpperIndex: position.tickUpperIndex,
|
|
@@ -1975,7 +1971,7 @@ export class Kamino {
|
|
|
1975
1971
|
throw Error(`Could not fetch Orca whirlpool position state with pubkey ${strategy.position.toString()}`);
|
|
1976
1972
|
}
|
|
1977
1973
|
const whirlpool = Whirlpool.decode(Buffer.from(whirlpoolAcc.data[0], 'base64'));
|
|
1978
|
-
const position =
|
|
1974
|
+
const position = OrcaPosition.decode(Buffer.from(positionAcc.data[0], 'base64'));
|
|
1979
1975
|
return this.getOrcaTokensBalances(strategy, whirlpool, position, mode);
|
|
1980
1976
|
} else if (strategy.strategyDex.toNumber() === dexToNumber('RAYDIUM')) {
|
|
1981
1977
|
const [poolStateAcc, positionAcc] = (
|
|
@@ -2049,7 +2045,7 @@ export class Kamino {
|
|
|
2049
2045
|
throw Error(`Could not fetch Orca whirlpool position state with pubkey ${strategy.position.toString()}`);
|
|
2050
2046
|
}
|
|
2051
2047
|
const whirlpool = Whirlpool.decode(Buffer.from(whirlpoolAcc.data[0], 'base64'));
|
|
2052
|
-
const position =
|
|
2048
|
+
const position = OrcaPosition.decode(Buffer.from(positionAcc.data[0], 'base64'));
|
|
2053
2049
|
|
|
2054
2050
|
return this.getOrcaBalances(
|
|
2055
2051
|
strategy,
|
|
@@ -2437,12 +2433,12 @@ export class Kamino {
|
|
|
2437
2433
|
if (positionPk === DEFAULT_PUBLIC_KEY) {
|
|
2438
2434
|
return { lowerPrice: ZERO, upperPrice: ZERO };
|
|
2439
2435
|
}
|
|
2440
|
-
const position = await
|
|
2436
|
+
const position = await OrcaPosition.fetch(this._rpc, positionPk, this._orcaService.getWhirlpoolProgramId());
|
|
2441
2437
|
if (!position) {
|
|
2442
2438
|
return { lowerPrice: ZERO, upperPrice: ZERO };
|
|
2443
2439
|
}
|
|
2444
|
-
const lowerPrice =
|
|
2445
|
-
const upperPrice =
|
|
2440
|
+
const lowerPrice = new Decimal(orcaTickIndexToPrice(position.tickLowerIndex, decimalsA, decimalsB));
|
|
2441
|
+
const upperPrice = new Decimal(orcaTickIndexToPrice(position.tickUpperIndex, decimalsA, decimalsB));
|
|
2446
2442
|
|
|
2447
2443
|
const positionRange: PositionRange = { lowerPrice, upperPrice };
|
|
2448
2444
|
|
|
@@ -2465,14 +2461,14 @@ export class Kamino {
|
|
|
2465
2461
|
if (!position) {
|
|
2466
2462
|
return { lowerPrice: ZERO, upperPrice: ZERO };
|
|
2467
2463
|
}
|
|
2468
|
-
const lowerPrice = sqrtPriceX64ToPrice(
|
|
2469
|
-
|
|
2464
|
+
const lowerPrice = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(
|
|
2465
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex),
|
|
2470
2466
|
decimalsA,
|
|
2471
2467
|
decimalsB
|
|
2472
2468
|
);
|
|
2473
2469
|
|
|
2474
|
-
const upperPrice = sqrtPriceX64ToPrice(
|
|
2475
|
-
|
|
2470
|
+
const upperPrice = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(
|
|
2471
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex),
|
|
2476
2472
|
decimalsA,
|
|
2477
2473
|
decimalsB
|
|
2478
2474
|
);
|
|
@@ -2554,17 +2550,21 @@ export class Kamino {
|
|
|
2554
2550
|
return whirlpoolMap;
|
|
2555
2551
|
};
|
|
2556
2552
|
|
|
2553
|
+
getAllWhirlpoolsFromAPI = async (tokens: Address[] = []): Promise<WhirlpoolAPIResponse[]> => {
|
|
2554
|
+
return (await this._orcaService.getOrcaWhirlpools(tokens));
|
|
2555
|
+
};
|
|
2556
|
+
|
|
2557
2557
|
/**
|
|
2558
2558
|
* Get a list of Orca positions from public keys
|
|
2559
2559
|
* @param positions
|
|
2560
2560
|
*/
|
|
2561
|
-
getOrcaPositions = async (positions: Address[]): Promise<(
|
|
2561
|
+
getOrcaPositions = async (positions: Address[]): Promise<(OrcaPosition | null)[]> => {
|
|
2562
2562
|
const nonDefaults = positions.filter((value) => value !== DEFAULT_PUBLIC_KEY);
|
|
2563
2563
|
const fetched = await batchFetch(nonDefaults, (chunk) =>
|
|
2564
|
-
|
|
2564
|
+
OrcaPosition.fetchMultiple(this._rpc, chunk, this._orcaService.getWhirlpoolProgramId())
|
|
2565
2565
|
);
|
|
2566
|
-
const fetchedMap: Record<string,
|
|
2567
|
-
(map: Record<Address,
|
|
2566
|
+
const fetchedMap: Record<string, OrcaPosition | null> = fetched.reduce(
|
|
2567
|
+
(map: Record<Address, OrcaPosition | null>, position, i) => {
|
|
2568
2568
|
map[nonDefaults[i]] = position;
|
|
2569
2569
|
return map;
|
|
2570
2570
|
},
|
|
@@ -4501,8 +4501,8 @@ export class Kamino {
|
|
|
4501
4501
|
tickLowerIndex: number,
|
|
4502
4502
|
tickUpperIndex: number
|
|
4503
4503
|
): Promise<LowerAndUpperTickPubkeys> => {
|
|
4504
|
-
const startTickIndex =
|
|
4505
|
-
const endTickIndex =
|
|
4504
|
+
const startTickIndex = orcaGetTickArrayStartTickIndex(tickLowerIndex, whirlpoolState.tickSpacing);
|
|
4505
|
+
const endTickIndex = orcaGetTickArrayStartTickIndex(tickUpperIndex, whirlpoolState.tickSpacing);
|
|
4506
4506
|
|
|
4507
4507
|
const [lowerTickPubkey, lowerTickBump] = await getProgramDerivedAddress({
|
|
4508
4508
|
seeds: [Buffer.from('tick_array'), addressEncoder.encode(whirlpool), Buffer.from(startTickIndex.toString())],
|
|
@@ -4526,8 +4526,8 @@ export class Kamino {
|
|
|
4526
4526
|
tickLowerIndex: number,
|
|
4527
4527
|
tickUpperIndex: number
|
|
4528
4528
|
): Promise<LowerAndUpperTickPubkeys> => {
|
|
4529
|
-
const startTickIndex =
|
|
4530
|
-
const endTickIndex =
|
|
4529
|
+
const startTickIndex = RaydiumTickUtils.getTickArrayStartIndexByTick(tickLowerIndex, poolState.tickSpacing);
|
|
4530
|
+
const endTickIndex = RaydiumTickUtils.getTickArrayStartIndexByTick(tickUpperIndex, poolState.tickSpacing);
|
|
4531
4531
|
|
|
4532
4532
|
const [lowerTickPubkey, lowerTickBump] = await getProgramDerivedAddress({
|
|
4533
4533
|
seeds: [Buffer.from('tick_array'), addressEncoder.encode(pool), i32ToBytes(startTickIndex)],
|
|
@@ -4767,12 +4767,12 @@ export class Kamino {
|
|
|
4767
4767
|
const decimalsA = await getMintDecimals(this._rpc, whirlpool.tokenMintA);
|
|
4768
4768
|
const decimalsB = await getMintDecimals(this._rpc, whirlpool.tokenMintB);
|
|
4769
4769
|
|
|
4770
|
-
const tickLowerIndex =
|
|
4771
|
-
|
|
4770
|
+
const tickLowerIndex = orcaGetTickArrayStartTickIndex(
|
|
4771
|
+
orcaPriceToTickIndex(priceLower.toNumber(), decimalsA, decimalsB),
|
|
4772
4772
|
whirlpool.tickSpacing
|
|
4773
4773
|
);
|
|
4774
|
-
const tickUpperIndex =
|
|
4775
|
-
|
|
4774
|
+
const tickUpperIndex = orcaGetTickArrayStartTickIndex(
|
|
4775
|
+
orcaPriceToTickIndex(priceUpper.toNumber(), decimalsA, decimalsB),
|
|
4776
4776
|
whirlpool.tickSpacing
|
|
4777
4777
|
);
|
|
4778
4778
|
|
|
@@ -4898,15 +4898,15 @@ export class Kamino {
|
|
|
4898
4898
|
const decimalsA = await getMintDecimals(this._rpc, poolState.tokenMint0);
|
|
4899
4899
|
const decimalsB = await getMintDecimals(this._rpc, poolState.tokenMint1);
|
|
4900
4900
|
|
|
4901
|
-
const tickLowerIndex =
|
|
4902
|
-
|
|
4901
|
+
const tickLowerIndex = RaydiumTickMath.getTickWithPriceAndTickspacing(
|
|
4902
|
+
RaydiumTickMath.roundPriceWithTickspacing(priceLower, poolState.tickSpacing, decimalsA, decimalsB),
|
|
4903
4903
|
poolState.tickSpacing,
|
|
4904
4904
|
decimalsA,
|
|
4905
4905
|
decimalsB
|
|
4906
4906
|
);
|
|
4907
4907
|
|
|
4908
|
-
const tickUpperIndex =
|
|
4909
|
-
|
|
4908
|
+
const tickUpperIndex = RaydiumTickMath.getTickWithPriceAndTickspacing(
|
|
4909
|
+
RaydiumTickMath.roundPriceWithTickspacing(priceUpper, poolState.tickSpacing, decimalsA, decimalsB),
|
|
4910
4910
|
poolState.tickSpacing,
|
|
4911
4911
|
decimalsA,
|
|
4912
4912
|
decimalsB
|
|
@@ -5461,7 +5461,7 @@ export class Kamino {
|
|
|
5461
5461
|
const { whirlpool: whilrpoolState } = await this.getWhirlpoolStateIfNotFetched(pool);
|
|
5462
5462
|
if (rebalanceTypeKind.kind === RebalanceType.Drift.kind) {
|
|
5463
5463
|
processedRebalanceParams[0] = new Decimal(
|
|
5464
|
-
|
|
5464
|
+
orcaGetNearestValidTickIndexFromTickIndex(rebalanceParams[0].toNumber(), whilrpoolState.tickSpacing)
|
|
5465
5465
|
);
|
|
5466
5466
|
}
|
|
5467
5467
|
}
|
|
@@ -5830,7 +5830,7 @@ export class Kamino {
|
|
|
5830
5830
|
return getPositionRangeFromExpanderParams(price, rebalanceParams[0], rebalanceParams[1]);
|
|
5831
5831
|
|
|
5832
5832
|
case RebalanceType.Autodrift.kind:
|
|
5833
|
-
const currentTickIndex =
|
|
5833
|
+
const currentTickIndex = orcaPriceToTickIndex(price.toNumber(), tokenADecimals, tokenBDecimals);
|
|
5834
5834
|
const startMidTick = new Decimal(currentTickIndex);
|
|
5835
5835
|
return getPositionRangeFromAutodriftParams(
|
|
5836
5836
|
dex,
|
|
@@ -5852,12 +5852,22 @@ export class Kamino {
|
|
|
5852
5852
|
const pool = strategyWithAddress.strategy.pool;
|
|
5853
5853
|
const dex = numberToDex(strategyWithAddress.strategy.strategyDex.toNumber());
|
|
5854
5854
|
|
|
5855
|
-
return this.getCurrentPriceFromPool(
|
|
5855
|
+
return this.getCurrentPriceFromPool(
|
|
5856
|
+
dex,
|
|
5857
|
+
pool,
|
|
5858
|
+
strategyWithAddress.strategy.tokenAMintDecimals.toNumber(),
|
|
5859
|
+
strategyWithAddress.strategy.tokenBMintDecimals.toNumber()
|
|
5860
|
+
);
|
|
5856
5861
|
}
|
|
5857
5862
|
|
|
5858
|
-
async getCurrentPriceFromPool(
|
|
5863
|
+
async getCurrentPriceFromPool(
|
|
5864
|
+
dex: Dex,
|
|
5865
|
+
pool: Address,
|
|
5866
|
+
tokenADecimals?: number,
|
|
5867
|
+
tokenBDecimals?: number
|
|
5868
|
+
): Promise<Decimal> {
|
|
5859
5869
|
if (dex === 'ORCA') {
|
|
5860
|
-
return this.getOrcaPoolPrice(pool);
|
|
5870
|
+
return this.getOrcaPoolPrice(pool, tokenADecimals, tokenBDecimals);
|
|
5861
5871
|
} else if (dex === 'RAYDIUM') {
|
|
5862
5872
|
return this.getRaydiumPoolPrice(pool);
|
|
5863
5873
|
} else if (dex === 'METEORA') {
|
|
@@ -6234,9 +6244,9 @@ export class Kamino {
|
|
|
6234
6244
|
/**
|
|
6235
6245
|
* Read the pool price for a specific dex and pool
|
|
6236
6246
|
*/
|
|
6237
|
-
async getPoolPrice(dex: Dex, pool: Address): Promise<Decimal> {
|
|
6247
|
+
async getPoolPrice(dex: Dex, pool: Address, tokenADecimals: number, tokenBDecimals: number): Promise<Decimal> {
|
|
6238
6248
|
if (dex === 'ORCA') {
|
|
6239
|
-
return this.getOrcaPoolPrice(pool);
|
|
6249
|
+
return this.getOrcaPoolPrice(pool, tokenADecimals, tokenBDecimals);
|
|
6240
6250
|
} else if (dex === 'RAYDIUM') {
|
|
6241
6251
|
return this.getRaydiumPoolPrice(pool);
|
|
6242
6252
|
} else if (dex === 'METEORA') {
|
|
@@ -6246,12 +6256,25 @@ export class Kamino {
|
|
|
6246
6256
|
}
|
|
6247
6257
|
}
|
|
6248
6258
|
|
|
6249
|
-
async getOrcaPoolPrice(pool: Address): Promise<Decimal> {
|
|
6250
|
-
|
|
6251
|
-
if (
|
|
6252
|
-
|
|
6259
|
+
async getOrcaPoolPrice(pool: Address, tokenADecimals?: number, tokenBDecimals?: number): Promise<Decimal> {
|
|
6260
|
+
// if the decimals are provided read from API, otherwise use RPC
|
|
6261
|
+
if (tokenADecimals && tokenBDecimals) {
|
|
6262
|
+
const whirlpool = await Whirlpool.fetch(this._rpc, pool, this._orcaService.getWhirlpoolProgramId());
|
|
6263
|
+
if (!whirlpool) {
|
|
6264
|
+
throw Error(`Could not fetch Whirlpool data for ${pool.toString()}`);
|
|
6265
|
+
}
|
|
6266
|
+
|
|
6267
|
+
return new Decimal(sqrtPriceToPrice(BigInt(whirlpool.sqrtPrice.toString()), tokenADecimals, tokenBDecimals));
|
|
6268
|
+
} else {
|
|
6269
|
+
const whirlpool = await this._orcaService.getOrcaWhirlpool(pool);
|
|
6270
|
+
if (!whirlpool) {
|
|
6271
|
+
throw Error(`Could not fetch Whirlpool data for ${pool.toString()}`);
|
|
6272
|
+
}
|
|
6273
|
+
|
|
6274
|
+
return new Decimal(
|
|
6275
|
+
sqrtPriceToPrice(BigInt(whirlpool.sqrtPrice.toString()), whirlpool.tokenA.decimals, whirlpool.tokenB.decimals)
|
|
6276
|
+
);
|
|
6253
6277
|
}
|
|
6254
|
-
return poolData.price;
|
|
6255
6278
|
}
|
|
6256
6279
|
|
|
6257
6280
|
async getRaydiumPoolPrice(pool: Address): Promise<Decimal> {
|
|
@@ -6260,7 +6283,7 @@ export class Kamino {
|
|
|
6260
6283
|
throw new Error(`Raydium poolState ${pool.toString()} is not found`);
|
|
6261
6284
|
}
|
|
6262
6285
|
|
|
6263
|
-
const price =
|
|
6286
|
+
const price = RaydiumSqrtPriceMath.sqrtPriceX64ToPrice(
|
|
6264
6287
|
poolState.sqrtPriceX64,
|
|
6265
6288
|
poolState.mintDecimals0,
|
|
6266
6289
|
poolState.mintDecimals1
|
|
@@ -6692,7 +6715,7 @@ export class Kamino {
|
|
|
6692
6715
|
*/
|
|
6693
6716
|
getStrategyAprApy = async (
|
|
6694
6717
|
strategy: Address | StrategyWithAddress,
|
|
6695
|
-
orcaPools?:
|
|
6718
|
+
orcaPools?: WhirlpoolAPIResponse[],
|
|
6696
6719
|
raydiumPools?: Pool[]
|
|
6697
6720
|
): Promise<WhirlpoolAprApy> => {
|
|
6698
6721
|
const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);
|
|
@@ -6717,7 +6740,7 @@ export class Kamino {
|
|
|
6717
6740
|
if (isOrca) {
|
|
6718
6741
|
const prices = await this.getAllPrices();
|
|
6719
6742
|
const collateralInfos = await this.getCollateralInfos();
|
|
6720
|
-
return this._orcaService.getStrategyWhirlpoolPoolAprApy(strategyState, collateralInfos, prices
|
|
6743
|
+
return this._orcaService.getStrategyWhirlpoolPoolAprApy(strategyState, collateralInfos, prices);
|
|
6721
6744
|
}
|
|
6722
6745
|
if (isRaydium) {
|
|
6723
6746
|
return this._raydiumService.getStrategyWhirlpoolPoolAprApy(strategyState, raydiumPools);
|
|
@@ -6951,10 +6974,10 @@ export class Kamino {
|
|
|
6951
6974
|
const decimalsA = poolState.mintDecimals0;
|
|
6952
6975
|
const decimalsB = poolState.mintDecimals1;
|
|
6953
6976
|
|
|
6954
|
-
const { amountA, amountB } =
|
|
6977
|
+
const { amountA, amountB } = RaydiumLiquidityMath.getAmountsFromLiquidity(
|
|
6955
6978
|
poolState.sqrtPriceX64,
|
|
6956
|
-
|
|
6957
|
-
|
|
6979
|
+
RaydiumSqrtPriceMath.priceToSqrtPriceX64(lowerPrice, decimalsA, decimalsB),
|
|
6980
|
+
RaydiumSqrtPriceMath.priceToSqrtPriceX64(upperPrice, decimalsA, decimalsB),
|
|
6958
6981
|
new BN(100_000_000),
|
|
6959
6982
|
true
|
|
6960
6983
|
);
|
|
@@ -6972,31 +6995,31 @@ export class Kamino {
|
|
|
6972
6995
|
const decimalsA = await getMintDecimals(this._rpc, tokenMintA);
|
|
6973
6996
|
const decimalsB = await getMintDecimals(this._rpc, tokenMintB);
|
|
6974
6997
|
|
|
6975
|
-
const tickLowerIndex =
|
|
6976
|
-
|
|
6998
|
+
const tickLowerIndex = orcaGetNearestValidTickIndexFromTickIndex(
|
|
6999
|
+
orcaPriceToTickIndex(lowerPrice.toNumber(), decimalsA, decimalsB),
|
|
6977
7000
|
whirlpoolState.tickSpacing
|
|
6978
7001
|
);
|
|
6979
|
-
const tickUpperIndex =
|
|
6980
|
-
|
|
7002
|
+
const tickUpperIndex = orcaGetNearestValidTickIndexFromTickIndex(
|
|
7003
|
+
orcaPriceToTickIndex(upperPrice.toNumber(), decimalsA, decimalsB),
|
|
6981
7004
|
whirlpoolState.tickSpacing
|
|
6982
7005
|
);
|
|
6983
7006
|
|
|
6984
|
-
const
|
|
6985
|
-
|
|
6986
|
-
tokenMintB: toLegacyPublicKey(tokenMintB),
|
|
6987
|
-
tickCurrentIndex: whirlpoolState.tickCurrentIndex,
|
|
6988
|
-
sqrtPrice: whirlpoolState.sqrtPrice,
|
|
6989
|
-
inputTokenMint: toLegacyPublicKey(tokenMintA),
|
|
6990
|
-
inputTokenAmount: new BN(collToLamportsDecimal(tokenAAmountToDeposit, decimalsA).toString()),
|
|
6991
|
-
tickLowerIndex,
|
|
6992
|
-
tickUpperIndex,
|
|
6993
|
-
slippageTolerance: defaultSlippagePercentage,
|
|
7007
|
+
const param: IncreaseLiquidityQuoteParam = {
|
|
7008
|
+
tokenA: BigInt(collToLamportsDecimal(tokenAAmountToDeposit, decimalsA).toString()),
|
|
6994
7009
|
};
|
|
6995
7010
|
|
|
6996
|
-
const addLiqResult:
|
|
7011
|
+
const addLiqResult: IncreaseLiquidityQuote = getIncreaseLiquidityQuote(
|
|
7012
|
+
param,
|
|
7013
|
+
whirlpoolState,
|
|
7014
|
+
tickLowerIndex,
|
|
7015
|
+
tickUpperIndex,
|
|
7016
|
+
defaultSlippagePercentageBPS,
|
|
7017
|
+
undefined,
|
|
7018
|
+
undefined
|
|
7019
|
+
);
|
|
6997
7020
|
return [
|
|
6998
|
-
lamportsToNumberDecimal(addLiqResult.
|
|
6999
|
-
lamportsToNumberDecimal(addLiqResult.
|
|
7021
|
+
lamportsToNumberDecimal(new Decimal(addLiqResult.tokenEstA.toString()), decimalsA),
|
|
7022
|
+
lamportsToNumberDecimal(new Decimal(addLiqResult.tokenEstB.toString()), decimalsB),
|
|
7000
7023
|
];
|
|
7001
7024
|
} else if (dex === 'METEORA') {
|
|
7002
7025
|
const poolState = await LbPair.fetch(this._rpc, pool, this._meteoraService.getMeteoraProgramId());
|
|
@@ -7118,9 +7141,7 @@ export class Kamino {
|
|
|
7118
7141
|
}
|
|
7119
7142
|
|
|
7120
7143
|
return this.calculateAmountsOrca({
|
|
7121
|
-
|
|
7122
|
-
tokenAMint: strategyState.tokenAMint,
|
|
7123
|
-
tokenBMint: strategyState.tokenBMint,
|
|
7144
|
+
whirlpoolState: whirlpool,
|
|
7124
7145
|
positionAddress: strategyState.position,
|
|
7125
7146
|
tokenAAmount,
|
|
7126
7147
|
tokenBAmount,
|
|
@@ -7135,16 +7156,12 @@ export class Kamino {
|
|
|
7135
7156
|
};
|
|
7136
7157
|
|
|
7137
7158
|
calculateAmountsOrca = async ({
|
|
7138
|
-
|
|
7139
|
-
tokenAMint,
|
|
7140
|
-
tokenBMint,
|
|
7159
|
+
whirlpoolState,
|
|
7141
7160
|
positionAddress,
|
|
7142
7161
|
tokenAAmount,
|
|
7143
7162
|
tokenBAmount,
|
|
7144
7163
|
}: {
|
|
7145
|
-
|
|
7146
|
-
tokenAMint: Address;
|
|
7147
|
-
tokenBMint: Address;
|
|
7164
|
+
whirlpoolState: Whirlpool;
|
|
7148
7165
|
positionAddress: Address;
|
|
7149
7166
|
tokenAAmount?: Decimal;
|
|
7150
7167
|
tokenBAmount?: Decimal;
|
|
@@ -7152,47 +7169,61 @@ export class Kamino {
|
|
|
7152
7169
|
if (!tokenAAmount && !tokenBAmount) {
|
|
7153
7170
|
return [new Decimal(0), new Decimal(0)];
|
|
7154
7171
|
}
|
|
7172
|
+
|
|
7155
7173
|
// Given A in ATA, calc how much A and B
|
|
7156
|
-
const
|
|
7157
|
-
const
|
|
7158
|
-
|
|
7174
|
+
const defaultSlippagePercentageBPS = 10;
|
|
7175
|
+
const positionState = await OrcaPosition.fetch(
|
|
7176
|
+
this._rpc,
|
|
7177
|
+
positionAddress,
|
|
7178
|
+
this._orcaService.getWhirlpoolProgramId()
|
|
7179
|
+
);
|
|
7180
|
+
if (!positionState) {
|
|
7181
|
+
throw new Error(`Unable to get Orca position for pubkey ${positionAddress}`);
|
|
7182
|
+
}
|
|
7159
7183
|
|
|
7160
|
-
|
|
7161
|
-
const primaryTokenMint = tokenAAmount ? tokenAMint : tokenBMint;
|
|
7162
|
-
const secondaryTokenAmount = tokenAAmount ? tokenBAmount : tokenAAmount;
|
|
7163
|
-
const secondaryTokenMint = tokenAAmount ? tokenBMint : tokenAMint;
|
|
7184
|
+
let computedAmounts: [Decimal, Decimal] = [new Decimal(0), new Decimal(0)];
|
|
7164
7185
|
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7186
|
+
if (tokenAAmount) {
|
|
7187
|
+
const tokenAForQuote = BigInt(tokenAAmount.toString());
|
|
7188
|
+
const params: IncreaseLiquidityQuoteParam = {
|
|
7189
|
+
tokenA: tokenAForQuote,
|
|
7190
|
+
};
|
|
7191
|
+
const estimatedGivenA: IncreaseLiquidityQuote = getIncreaseLiquidityQuote(
|
|
7192
|
+
params,
|
|
7193
|
+
whirlpoolState,
|
|
7194
|
+
positionState.tickLowerIndex,
|
|
7195
|
+
positionState.tickUpperIndex,
|
|
7196
|
+
defaultSlippagePercentageBPS,
|
|
7197
|
+
undefined, // todo: use new Wirlpool state and read transfer fees
|
|
7198
|
+
undefined
|
|
7199
|
+
);
|
|
7200
|
+
computedAmounts = [
|
|
7201
|
+
new Decimal(estimatedGivenA.tokenEstA.toString()),
|
|
7202
|
+
new Decimal(estimatedGivenA.tokenEstB.toString()),
|
|
7203
|
+
];
|
|
7204
|
+
}
|
|
7174
7205
|
|
|
7175
|
-
if (
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
params = {
|
|
7180
|
-
positionAddress,
|
|
7181
|
-
tokenMint: secondaryTokenMint,
|
|
7182
|
-
tokenAmount: new BN(secondaryTokenAmount.toString()),
|
|
7183
|
-
refresh: true,
|
|
7184
|
-
slippageTolerance: defaultSlippagePercentage,
|
|
7206
|
+
if (tokenBAmount && computedAmounts[1] > tokenBAmount) {
|
|
7207
|
+
const tokenBForQuote = BigInt(tokenBAmount.toString());
|
|
7208
|
+
const params: IncreaseLiquidityQuoteParam = {
|
|
7209
|
+
tokenB: tokenBForQuote,
|
|
7185
7210
|
};
|
|
7186
|
-
const
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7211
|
+
const estimatedGivenB: IncreaseLiquidityQuote = getIncreaseLiquidityQuote(
|
|
7212
|
+
params,
|
|
7213
|
+
whirlpoolState,
|
|
7214
|
+
positionState.tickLowerIndex,
|
|
7215
|
+
positionState.tickUpperIndex,
|
|
7216
|
+
defaultSlippagePercentageBPS,
|
|
7217
|
+
undefined, // todo: use new Wirlpool state and read transfer fees
|
|
7218
|
+
undefined
|
|
7219
|
+
);
|
|
7220
|
+
computedAmounts = [
|
|
7221
|
+
new Decimal(estimatedGivenB.tokenEstA.toString()),
|
|
7222
|
+
new Decimal(estimatedGivenB.tokenEstB.toString()),
|
|
7190
7223
|
];
|
|
7191
7224
|
}
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
new Decimal(estimatedGivenPrimary.estTokenB.toString()),
|
|
7195
|
-
];
|
|
7225
|
+
|
|
7226
|
+
return computedAmounts;
|
|
7196
7227
|
};
|
|
7197
7228
|
|
|
7198
7229
|
calculateAmountsRaydium = async ({
|
|
@@ -7224,18 +7255,18 @@ export class Kamino {
|
|
|
7224
7255
|
}
|
|
7225
7256
|
|
|
7226
7257
|
if (tokenAAmount && tokenBAmount && tokenAAmount.gt(0) && tokenBAmount.gt(0)) {
|
|
7227
|
-
const liquidity =
|
|
7258
|
+
const liquidity = RaydiumLiquidityMath.getLiquidityFromTokenAmounts(
|
|
7228
7259
|
poolState.sqrtPriceX64,
|
|
7229
|
-
|
|
7230
|
-
|
|
7260
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex),
|
|
7261
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex),
|
|
7231
7262
|
new BN(tokenAAmount.toString()),
|
|
7232
7263
|
new BN(tokenBAmount.toString())
|
|
7233
7264
|
);
|
|
7234
7265
|
|
|
7235
|
-
const { amountA, amountB } =
|
|
7266
|
+
const { amountA, amountB } = RaydiumLiquidityMath.getAmountsFromLiquidity(
|
|
7236
7267
|
poolState.sqrtPriceX64,
|
|
7237
|
-
|
|
7238
|
-
|
|
7268
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex),
|
|
7269
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex),
|
|
7239
7270
|
liquidity,
|
|
7240
7271
|
true
|
|
7241
7272
|
);
|
|
@@ -7245,10 +7276,10 @@ export class Kamino {
|
|
|
7245
7276
|
const primaryTokenAmount = tokenAAmount || tokenBAmount;
|
|
7246
7277
|
const secondaryTokenAmount = tokenAAmount ? tokenBAmount : tokenAAmount;
|
|
7247
7278
|
|
|
7248
|
-
const { amountA, amountB } =
|
|
7279
|
+
const { amountA, amountB } = RaydiumLiquidityMath.getAmountsFromLiquidity(
|
|
7249
7280
|
poolState.sqrtPriceX64,
|
|
7250
|
-
|
|
7251
|
-
|
|
7281
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickLowerIndex),
|
|
7282
|
+
RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(position.tickUpperIndex),
|
|
7252
7283
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
7253
7284
|
new BN(primaryTokenAmount!.plus(secondaryTokenAmount || 0)!.toString()), // safe to use ! here because we check in the beginning that at least one of the amounts are not undefined;
|
|
7254
7285
|
true
|
|
@@ -7447,26 +7478,30 @@ export class Kamino {
|
|
|
7447
7478
|
throw Error(`Could not fetch whirlpool state with pubkey ${strategyState.pool.toString()}`);
|
|
7448
7479
|
}
|
|
7449
7480
|
|
|
7450
|
-
const position = await
|
|
7481
|
+
const position = await OrcaPosition.fetch(
|
|
7482
|
+
this._rpc,
|
|
7483
|
+
strategyState.position,
|
|
7484
|
+
this._orcaService.getWhirlpoolProgramId()
|
|
7485
|
+
);
|
|
7451
7486
|
if (!position) {
|
|
7452
7487
|
throw new Error(`Whirlpool position ${strategyState.position} does not exist`);
|
|
7453
7488
|
}
|
|
7454
7489
|
|
|
7455
|
-
const params:
|
|
7456
|
-
|
|
7457
|
-
tokenMintB: toLegacyPublicKey(strategyState.tokenBMint),
|
|
7458
|
-
tickCurrentIndex: whirlpool.tickCurrentIndex,
|
|
7459
|
-
sqrtPrice: whirlpool.sqrtPrice,
|
|
7460
|
-
inputTokenMint: toLegacyPublicKey(strategyState.tokenAMint),
|
|
7461
|
-
inputTokenAmount: amountA,
|
|
7462
|
-
tickLowerIndex: position.tickLowerIndex,
|
|
7463
|
-
tickUpperIndex: position.tickUpperIndex,
|
|
7464
|
-
slippageTolerance: defaultSlippagePercentage,
|
|
7490
|
+
const params: IncreaseLiquidityQuoteParam = {
|
|
7491
|
+
tokenA: BigInt(amountA.toString()),
|
|
7465
7492
|
};
|
|
7466
7493
|
|
|
7467
|
-
const quote:
|
|
7494
|
+
const quote: IncreaseLiquidityQuote = getIncreaseLiquidityQuote(
|
|
7495
|
+
params,
|
|
7496
|
+
whirlpool,
|
|
7497
|
+
position.tickLowerIndex,
|
|
7498
|
+
position.tickUpperIndex,
|
|
7499
|
+
defaultSlippagePercentageBPS,
|
|
7500
|
+
undefined,
|
|
7501
|
+
undefined
|
|
7502
|
+
);
|
|
7468
7503
|
|
|
7469
|
-
return { amountSlippageA: quote.
|
|
7504
|
+
return { amountSlippageA: new BN(quote.tokenEstA.toString()), amountSlippageB: new BN(quote.tokenEstB.toString()) };
|
|
7470
7505
|
}
|
|
7471
7506
|
|
|
7472
7507
|
private async getDepositRatioFromAMeteora(
|
|
@@ -7517,26 +7552,30 @@ export class Kamino {
|
|
|
7517
7552
|
throw Error(`Could not fetch whirlpool state with pubkey ${strategyState.pool.toString()}`);
|
|
7518
7553
|
}
|
|
7519
7554
|
|
|
7520
|
-
const position = await
|
|
7555
|
+
const position = await OrcaPosition.fetch(
|
|
7556
|
+
this._rpc,
|
|
7557
|
+
strategyState.position,
|
|
7558
|
+
this._orcaService.getWhirlpoolProgramId()
|
|
7559
|
+
);
|
|
7521
7560
|
if (!position) {
|
|
7522
7561
|
throw new Error(`Whirlpool position ${strategyState.position} does not exist`);
|
|
7523
7562
|
}
|
|
7524
7563
|
|
|
7525
|
-
const
|
|
7526
|
-
|
|
7527
|
-
tokenMintB: toLegacyPublicKey(strategyState.tokenBMint),
|
|
7528
|
-
tickCurrentIndex: whirlpool.tickCurrentIndex,
|
|
7529
|
-
sqrtPrice: whirlpool.sqrtPrice,
|
|
7530
|
-
inputTokenMint: toLegacyPublicKey(strategyState.tokenBMint),
|
|
7531
|
-
inputTokenAmount: amountB,
|
|
7532
|
-
tickLowerIndex: position.tickLowerIndex,
|
|
7533
|
-
tickUpperIndex: position.tickUpperIndex,
|
|
7534
|
-
slippageTolerance: defaultSlippagePercentage,
|
|
7564
|
+
const param: IncreaseLiquidityQuoteParam = {
|
|
7565
|
+
tokenB: BigInt(amountB.toString()),
|
|
7535
7566
|
};
|
|
7536
7567
|
|
|
7537
|
-
const quote:
|
|
7568
|
+
const quote: IncreaseLiquidityQuote = getIncreaseLiquidityQuote(
|
|
7569
|
+
param,
|
|
7570
|
+
whirlpool,
|
|
7571
|
+
position.tickLowerIndex,
|
|
7572
|
+
position.tickUpperIndex,
|
|
7573
|
+
defaultSlippagePercentageBPS,
|
|
7574
|
+
undefined,
|
|
7575
|
+
undefined
|
|
7576
|
+
);
|
|
7538
7577
|
|
|
7539
|
-
return { amountSlippageA: quote.
|
|
7578
|
+
return { amountSlippageA: new BN(quote.tokenEstA.toString()), amountSlippageB: new BN(quote.tokenEstB.toString()) };
|
|
7540
7579
|
};
|
|
7541
7580
|
|
|
7542
7581
|
private getDepositRatioFromARaydium = async (
|
|
@@ -7559,11 +7598,16 @@ export class Kamino {
|
|
|
7559
7598
|
throw new Error(`Raydium pool ${strategyState.pool.toString()} could not be found.`);
|
|
7560
7599
|
}
|
|
7561
7600
|
|
|
7562
|
-
const lowerSqrtPriceX64 =
|
|
7563
|
-
const upperSqrtPriceX64 =
|
|
7601
|
+
const lowerSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(positionState.tickLowerIndex);
|
|
7602
|
+
const upperSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(positionState.tickUpperIndex);
|
|
7564
7603
|
|
|
7565
|
-
const liqudity =
|
|
7566
|
-
|
|
7604
|
+
const liqudity = RaydiumLiquidityMath.getLiquidityFromTokenAmountA(
|
|
7605
|
+
lowerSqrtPriceX64,
|
|
7606
|
+
upperSqrtPriceX64,
|
|
7607
|
+
amountA,
|
|
7608
|
+
false
|
|
7609
|
+
);
|
|
7610
|
+
const amountsSlippage = RaydiumLiquidityMath.getAmountsFromLiquidityWithSlippage(
|
|
7567
7611
|
poolState.sqrtPriceX64,
|
|
7568
7612
|
lowerSqrtPriceX64,
|
|
7569
7613
|
upperSqrtPriceX64,
|
|
@@ -7596,11 +7640,11 @@ export class Kamino {
|
|
|
7596
7640
|
throw new Error(`Raydium pool ${strategyState.pool.toString()} could not be found.`);
|
|
7597
7641
|
}
|
|
7598
7642
|
|
|
7599
|
-
const lowerSqrtPriceX64 =
|
|
7600
|
-
const upperSqrtPriceX64 =
|
|
7643
|
+
const lowerSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(positionState.tickLowerIndex);
|
|
7644
|
+
const upperSqrtPriceX64 = RaydiumSqrtPriceMath.getSqrtPriceX64FromTick(positionState.tickUpperIndex);
|
|
7601
7645
|
|
|
7602
|
-
const liqudity =
|
|
7603
|
-
const amountsSlippage =
|
|
7646
|
+
const liqudity = RaydiumLiquidityMath.getLiquidityFromTokenAmountB(lowerSqrtPriceX64, upperSqrtPriceX64, amountB);
|
|
7647
|
+
const amountsSlippage = RaydiumLiquidityMath.getAmountsFromLiquidityWithSlippage(
|
|
7604
7648
|
poolState.sqrtPriceX64,
|
|
7605
7649
|
lowerSqrtPriceX64,
|
|
7606
7650
|
upperSqrtPriceX64,
|
|
@@ -7869,8 +7913,11 @@ export class Kamino {
|
|
|
7869
7913
|
|
|
7870
7914
|
const decimalsA = await getMintDecimals(this._rpc, whilrpoolState.tokenMintA);
|
|
7871
7915
|
const decimalsB = await getMintDecimals(this._rpc, whilrpoolState.tokenMintB);
|
|
7872
|
-
const tickIndex =
|
|
7873
|
-
|
|
7916
|
+
const tickIndex = orcaGetTickArrayStartTickIndex(
|
|
7917
|
+
orcaPriceToTickIndex(price.toNumber(), decimalsA, decimalsB),
|
|
7918
|
+
whilrpoolState.tickSpacing
|
|
7919
|
+
);
|
|
7920
|
+
const startTickIndex = orcaGetTickArrayStartTickIndex(tickIndex, whilrpoolState.tickSpacing);
|
|
7874
7921
|
|
|
7875
7922
|
const [startTickIndexPk, _startTickIndexBump] = await getTickArray(
|
|
7876
7923
|
this._orcaService.getWhirlpoolProgramId(),
|