@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.
- package/dist/Kamino.d.ts +16 -14
- package/dist/Kamino.d.ts.map +1 -1
- package/dist/Kamino.js +114 -125
- 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/JupService.d.ts.map +1 -1
- package/dist/services/MeteoraService.d.ts.map +1 -1
- package/dist/services/MeteoraService.js +4 -1
- package/dist/services/MeteoraService.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 +133 -101
- 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/services/RaydiumService.d.ts.map +1 -1
- package/dist/services/RaydiumService.js +7 -1
- package/dist/services/RaydiumService.js.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/lookupTable.d.ts.map +1 -1
- package/dist/utils/lookupTable.js +1 -1
- package/dist/utils/lookupTable.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/transactions.d.ts.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 +10 -9
- package/src/Kamino.ts +271 -215
- 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/MeteoraService.ts +5 -2
- package/src/services/OrcaService.ts +163 -126
- package/src/services/OrcaWhirlpoolsResponse.ts +69 -101
- package/src/services/RaydiumService.ts +8 -2
- package/src/utils/farms.ts +0 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/lookupTable.ts +2 -2
- 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/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
|
|
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,
|
|
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.
|
|
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.
|
|
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,
|
|
552
|
-
tokenMintA: (0, kit_1.address)(pool.
|
|
553
|
-
tokenMintB: (0, kit_1.address)(pool.
|
|
554
|
-
tvl: pool.
|
|
555
|
-
feeRate: new decimal_js_1.default(pool.
|
|
556
|
-
volumeOnLast7d: pool.
|
|
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.
|
|
617
|
-
if ((element.
|
|
618
|
-
(element.
|
|
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,
|
|
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,
|
|
1042
|
-
const lowerPrice = (0,
|
|
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:
|
|
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: [
|
|
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: [
|
|
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,
|
|
1530
|
-
const upperPrice = (0,
|
|
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 =
|
|
1543
|
-
const upperPrice =
|
|
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,
|
|
2945
|
-
const endTickIndex = (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,
|
|
3094
|
-
const tickUpperIndex = (0,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
4135
|
-
if (
|
|
4136
|
-
|
|
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: [
|
|
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
|
|
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,
|
|
4662
|
-
const tickUpperIndex = (0,
|
|
4663
|
-
const
|
|
4664
|
-
|
|
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,
|
|
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.
|
|
4677
|
-
(0, utils_1.lamportsToNumberDecimal)(addLiqResult.
|
|
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
|
-
|
|
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 ({
|
|
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
|
|
4798
|
-
const
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
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
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
new decimal_js_1.default(
|
|
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
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
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
|
-
|
|
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,
|
|
5022
|
-
return { amountSlippageA: quote.
|
|
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:
|
|
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:
|
|
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
|
|
5056
|
-
|
|
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,
|
|
5067
|
-
return { amountSlippageA: quote.
|
|
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,
|
|
5282
|
-
const startTickIndex = (0,
|
|
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
|