@kamino-finance/klend-sdk 7.3.3 → 7.3.4
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/classes/manager.d.ts +21 -0
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +25 -0
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/vault.d.ts +16 -1
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +148 -42
- package/dist/classes/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +40 -0
- package/src/classes/vault.ts +251 -65
package/dist/classes/vault.js
CHANGED
|
@@ -697,6 +697,12 @@ class KaminoVaultClient {
|
|
|
697
697
|
* @returns - an instance of DepositIxs which contains the instructions to deposit in vault and the instructions to stake the shares in the farm if the vault has a farm
|
|
698
698
|
*/
|
|
699
699
|
async depositIxs(user, vault, tokenAmount, vaultReservesMap, farmState) {
|
|
700
|
+
return this.buildShareEntryIxs('deposit', user, vault, tokenAmount, vaultReservesMap, farmState);
|
|
701
|
+
}
|
|
702
|
+
async buySharesIxs(user, vault, tokenAmount, vaultReservesMap, farmState) {
|
|
703
|
+
return this.buildShareEntryIxs('buy', user, vault, tokenAmount, vaultReservesMap, farmState);
|
|
704
|
+
}
|
|
705
|
+
async buildShareEntryIxs(mode, user, vault, tokenAmount, vaultReservesMap, farmState) {
|
|
700
706
|
const vaultState = await vault.getState();
|
|
701
707
|
const tokenProgramID = vaultState.tokenProgram;
|
|
702
708
|
const userTokenAta = await (0, lib_1.getAssociatedTokenAddress)(vaultState.tokenMint, user.address, tokenProgramID);
|
|
@@ -721,40 +727,63 @@ class KaminoVaultClient {
|
|
|
721
727
|
]);
|
|
722
728
|
createAtasIxs.push(createSharesAtaIxs);
|
|
723
729
|
const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
730
|
+
const tokenAmountLamports = (0, utils_1.numberToLamportsDecimal)(tokenAmount, vaultState.tokenMintDecimals.toNumber()).floor();
|
|
731
|
+
let entryIx;
|
|
732
|
+
if (mode === 'deposit') {
|
|
733
|
+
const depositAccounts = {
|
|
734
|
+
user,
|
|
735
|
+
vaultState: vault.address,
|
|
736
|
+
tokenVault: vaultState.tokenVault,
|
|
737
|
+
tokenMint: vaultState.tokenMint,
|
|
738
|
+
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
739
|
+
sharesMint: vaultState.sharesMint,
|
|
740
|
+
userTokenAta,
|
|
741
|
+
userSharesAta,
|
|
742
|
+
tokenProgram: tokenProgramID,
|
|
743
|
+
klendProgram: this._kaminoLendProgramId,
|
|
744
|
+
sharesTokenProgram: token_1.TOKEN_PROGRAM_ADDRESS,
|
|
745
|
+
eventAuthority,
|
|
746
|
+
program: this._kaminoVaultProgramId,
|
|
747
|
+
};
|
|
748
|
+
const depositArgs = {
|
|
749
|
+
maxAmount: new bn_js_1.default(tokenAmountLamports.toString()),
|
|
750
|
+
};
|
|
751
|
+
entryIx = (0, instructions_1.deposit)(depositArgs, depositAccounts, undefined, this._kaminoVaultProgramId);
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
const buyAccounts = {
|
|
755
|
+
user,
|
|
756
|
+
vaultState: vault.address,
|
|
757
|
+
tokenVault: vaultState.tokenVault,
|
|
758
|
+
tokenMint: vaultState.tokenMint,
|
|
759
|
+
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
760
|
+
sharesMint: vaultState.sharesMint,
|
|
761
|
+
userTokenAta,
|
|
762
|
+
userSharesAta,
|
|
763
|
+
tokenProgram: tokenProgramID,
|
|
764
|
+
klendProgram: this._kaminoLendProgramId,
|
|
765
|
+
sharesTokenProgram: token_1.TOKEN_PROGRAM_ADDRESS,
|
|
766
|
+
eventAuthority,
|
|
767
|
+
program: this._kaminoVaultProgramId,
|
|
768
|
+
};
|
|
769
|
+
const buyArgs = {
|
|
770
|
+
maxAmount: new bn_js_1.default(tokenAmountLamports.toString()),
|
|
771
|
+
};
|
|
772
|
+
entryIx = (0, instructions_1.buy)(buyArgs, buyAccounts, undefined, this._kaminoVaultProgramId);
|
|
773
|
+
}
|
|
743
774
|
const vaultReserves = this.getVaultReserves(vaultState);
|
|
744
775
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
745
|
-
|
|
746
|
-
const
|
|
747
|
-
depositIxs: [...createAtasIxs,
|
|
776
|
+
entryIx = this.appendRemainingAccountsForVaultReserves(entryIx, vaultReserves, vaultReservesState);
|
|
777
|
+
const result = {
|
|
778
|
+
depositIxs: [...createAtasIxs, entryIx, ...closeAtasIxs],
|
|
748
779
|
stakeInFarmIfNeededIxs: [],
|
|
749
780
|
};
|
|
750
|
-
// if there is no farm, we can return the deposit instructions, otherwise include the stake ix in the response
|
|
751
781
|
if (!(await vault.hasFarm())) {
|
|
752
|
-
return
|
|
782
|
+
return result;
|
|
753
783
|
}
|
|
754
|
-
// if there is a farm, stake the shares
|
|
755
784
|
const stakeSharesIxs = await this.stakeSharesIxs(user, vault, undefined, farmState);
|
|
756
|
-
|
|
757
|
-
return
|
|
785
|
+
result.stakeInFarmIfNeededIxs = stakeSharesIxs;
|
|
786
|
+
return result;
|
|
758
787
|
}
|
|
759
788
|
/**
|
|
760
789
|
* This function creates instructions to stake the shares in the vault farm if the vault has a farm
|
|
@@ -788,6 +817,22 @@ class KaminoVaultClient {
|
|
|
788
817
|
* @returns an array of instructions to create missing ATAs if needed and the withdraw instructions
|
|
789
818
|
*/
|
|
790
819
|
async withdrawIxs(user, vault, shareAmountToWithdraw, slot, vaultReservesMap, farmState) {
|
|
820
|
+
return this.buildShareExitIxs('withdraw', user, vault, shareAmountToWithdraw, slot, vaultReservesMap, farmState);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* This function will return the missing ATA creation instructions, as well as one or multiple withdraw instructions, based on how many reserves it's needed to withdraw from. This might have to be split in multiple transactions
|
|
824
|
+
* @param user - user to sell shares for vault tokens
|
|
825
|
+
* @param vault - vault to sell shares from
|
|
826
|
+
* @param shareAmount - share amount to sell (in tokens, not lamports), in order to withdraw everything, any value > user share amount
|
|
827
|
+
* @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
|
|
828
|
+
* @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
|
|
829
|
+
* @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
|
|
830
|
+
* @returns an array of instructions to create missing ATAs if needed and the withdraw instructions
|
|
831
|
+
*/
|
|
832
|
+
async sellSharesIxs(user, vault, shareAmountToWithdraw, slot, vaultReservesMap, farmState) {
|
|
833
|
+
return this.buildShareExitIxs('sell', user, vault, shareAmountToWithdraw, slot, vaultReservesMap, farmState);
|
|
834
|
+
}
|
|
835
|
+
async buildShareExitIxs(mode, user, vault, shareAmountToWithdraw, slot, vaultReservesMap, farmState) {
|
|
791
836
|
const vaultState = await vault.getState();
|
|
792
837
|
const hasFarm = await vault.hasFarm();
|
|
793
838
|
const withdrawIxs = {
|
|
@@ -834,10 +879,21 @@ class KaminoVaultClient {
|
|
|
834
879
|
withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.unstakeIx);
|
|
835
880
|
withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.withdrawIx);
|
|
836
881
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
882
|
+
const hasAllocatedReserves = vaultState.vaultAllocationStrategy.some((allocation) => allocation.reserve !== lib_1.DEFAULT_PUBLIC_KEY);
|
|
883
|
+
if (hasAllocatedReserves) {
|
|
884
|
+
const reserveExitBuilder = mode === 'withdraw'
|
|
885
|
+
? (params) => this.withdrawIx(params.user, params.vault, params.vaultState, params.marketAddress, params.reserve, params.userSharesAta, params.userTokenAta, params.shareAmountLamports, params.vaultReservesState)
|
|
886
|
+
: (params) => this.sellIx(params.user, params.vault, params.vaultState, params.marketAddress, params.reserve, params.userSharesAta, params.userTokenAta, params.shareAmountLamports, params.vaultReservesState);
|
|
887
|
+
const withdrawFromVaultIxs = await this.buildReserveExitIxs({
|
|
888
|
+
user,
|
|
889
|
+
vault,
|
|
890
|
+
vaultState,
|
|
891
|
+
shareAmount: sharesToWithdraw,
|
|
892
|
+
allUserShares: totalUserShares,
|
|
893
|
+
slot,
|
|
894
|
+
vaultReservesMap,
|
|
895
|
+
builder: reserveExitBuilder,
|
|
896
|
+
});
|
|
841
897
|
withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
|
|
842
898
|
}
|
|
843
899
|
else {
|
|
@@ -879,8 +935,7 @@ class KaminoVaultClient {
|
|
|
879
935
|
const withdrawFromAvailableIxn = await this.withdrawFromAvailableIx(user, vault, vaultState, userSharesAta, userTokenAta, shareLamportsToWithdraw);
|
|
880
936
|
return [createAtaIx, withdrawFromAvailableIxn];
|
|
881
937
|
}
|
|
882
|
-
async
|
|
883
|
-
const vaultState = await vault.getState();
|
|
938
|
+
async buildReserveExitIxs({ user, vault, vaultState, shareAmount, allUserShares, slot, vaultReservesMap, builder, }) {
|
|
884
939
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
885
940
|
const userSharesAta = await (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user.address);
|
|
886
941
|
const [{ ata: userTokenAta, createAtaIx }] = await (0, utils_2.createAtasIdempotent)(user, [
|
|
@@ -901,8 +956,10 @@ class KaminoVaultClient {
|
|
|
901
956
|
const reserveWithSharesAmountToWithdraw = [];
|
|
902
957
|
let isFirstWithdraw = true;
|
|
903
958
|
if (tokenLeftToWithdraw.lte(0)) {
|
|
904
|
-
// Availabe enough to withdraw all - using the first existent reserve
|
|
905
959
|
const firstReserve = vaultState.vaultAllocationStrategy.find((reserve) => reserve.reserve !== lib_1.DEFAULT_PUBLIC_KEY);
|
|
960
|
+
if (!firstReserve) {
|
|
961
|
+
throw new Error('No reserve available to satisfy withdraw request');
|
|
962
|
+
}
|
|
906
963
|
if (withdrawAllShares) {
|
|
907
964
|
reserveWithSharesAmountToWithdraw.push({
|
|
908
965
|
reserve: firstReserve.reserve,
|
|
@@ -917,13 +974,11 @@ class KaminoVaultClient {
|
|
|
917
974
|
}
|
|
918
975
|
}
|
|
919
976
|
else {
|
|
920
|
-
// Get decreasing order sorted available liquidity to withdraw from each reserve allocated to
|
|
921
977
|
const reserveAllocationAvailableLiquidityToWithdraw = await this.getReserveAllocationAvailableLiquidityToWithdraw(vault, slot, vaultReservesState);
|
|
922
|
-
// sort
|
|
923
978
|
const reserveAllocationAvailableLiquidityToWithdrawSorted = [
|
|
924
979
|
...reserveAllocationAvailableLiquidityToWithdraw.entries(),
|
|
925
980
|
].sort((a, b) => b[1].sub(a[1]).toNumber());
|
|
926
|
-
reserveAllocationAvailableLiquidityToWithdrawSorted.forEach(([key, availableLiquidityToWithdraw]
|
|
981
|
+
reserveAllocationAvailableLiquidityToWithdrawSorted.forEach(([key, availableLiquidityToWithdraw]) => {
|
|
927
982
|
if (tokenLeftToWithdraw.gt(0)) {
|
|
928
983
|
let tokensToWithdrawFromReserve = decimal_js_1.default.min(tokenLeftToWithdraw, availableLiquidityToWithdraw);
|
|
929
984
|
if (isFirstWithdraw) {
|
|
@@ -934,7 +989,6 @@ class KaminoVaultClient {
|
|
|
934
989
|
reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: new decimal_js_1.default(utils_2.U64_MAX.toString()) });
|
|
935
990
|
}
|
|
936
991
|
else {
|
|
937
|
-
// round up to the nearest integer the shares to withdraw
|
|
938
992
|
const sharesToWithdrawFromReserve = tokensToWithdrawFromReserve.mul(sharesPerToken).floor();
|
|
939
993
|
reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: sharesToWithdrawFromReserve });
|
|
940
994
|
}
|
|
@@ -944,15 +998,24 @@ class KaminoVaultClient {
|
|
|
944
998
|
}
|
|
945
999
|
const withdrawIxs = [];
|
|
946
1000
|
withdrawIxs.push(createAtaIx);
|
|
947
|
-
for (
|
|
948
|
-
const reserveWithTokens = reserveWithSharesAmountToWithdraw[reserveIndex];
|
|
1001
|
+
for (const reserveWithTokens of reserveWithSharesAmountToWithdraw) {
|
|
949
1002
|
const reserveState = vaultReservesState.get(reserveWithTokens.reserve);
|
|
950
1003
|
if (reserveState === undefined) {
|
|
951
1004
|
throw new Error(`Reserve ${reserveWithTokens.reserve} not found in vault reserves map`);
|
|
952
1005
|
}
|
|
953
1006
|
const marketAddress = reserveState.state.lendingMarket;
|
|
954
|
-
const
|
|
955
|
-
|
|
1007
|
+
const exitIx = await builder({
|
|
1008
|
+
user,
|
|
1009
|
+
vault,
|
|
1010
|
+
vaultState,
|
|
1011
|
+
marketAddress,
|
|
1012
|
+
reserve: { address: reserveWithTokens.reserve, state: reserveState.state },
|
|
1013
|
+
userSharesAta,
|
|
1014
|
+
userTokenAta,
|
|
1015
|
+
shareAmountLamports: reserveWithTokens.shares,
|
|
1016
|
+
vaultReservesState,
|
|
1017
|
+
});
|
|
1018
|
+
withdrawIxs.push(exitIx);
|
|
956
1019
|
}
|
|
957
1020
|
return withdrawIxs;
|
|
958
1021
|
}
|
|
@@ -1164,6 +1227,49 @@ class KaminoVaultClient {
|
|
|
1164
1227
|
sellIxn = this.appendRemainingAccountsForVaultReserves(sellIxn, vaultReserves, vaultReservesState);
|
|
1165
1228
|
return sellIxn;
|
|
1166
1229
|
}
|
|
1230
|
+
async withdrawIx(user, vault, vaultState, marketAddress, reserve, userSharesAta, userTokenAta, shareAmountLamports, vaultReservesState) {
|
|
1231
|
+
const [lendingMarketAuth] = await (0, utils_2.lendingMarketAuthPda)(marketAddress, this._kaminoLendProgramId);
|
|
1232
|
+
const globalConfig = await getKvaultGlobalConfigPda(this._kaminoVaultProgramId);
|
|
1233
|
+
const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
|
|
1234
|
+
const withdrawAccounts = {
|
|
1235
|
+
withdrawFromAvailable: {
|
|
1236
|
+
user,
|
|
1237
|
+
vaultState: vault.address,
|
|
1238
|
+
globalConfig: globalConfig,
|
|
1239
|
+
tokenVault: vaultState.tokenVault,
|
|
1240
|
+
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
1241
|
+
userTokenAta: userTokenAta,
|
|
1242
|
+
tokenMint: vaultState.tokenMint,
|
|
1243
|
+
userSharesAta: userSharesAta,
|
|
1244
|
+
sharesMint: vaultState.sharesMint,
|
|
1245
|
+
tokenProgram: vaultState.tokenProgram,
|
|
1246
|
+
sharesTokenProgram: token_1.TOKEN_PROGRAM_ADDRESS,
|
|
1247
|
+
klendProgram: this._kaminoLendProgramId,
|
|
1248
|
+
eventAuthority: eventAuthority,
|
|
1249
|
+
program: this._kaminoVaultProgramId,
|
|
1250
|
+
},
|
|
1251
|
+
withdrawFromReserveAccounts: {
|
|
1252
|
+
vaultState: vault.address,
|
|
1253
|
+
reserve: reserve.address,
|
|
1254
|
+
ctokenVault: await getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId),
|
|
1255
|
+
lendingMarket: marketAddress,
|
|
1256
|
+
lendingMarketAuthority: lendingMarketAuth,
|
|
1257
|
+
reserveLiquiditySupply: reserve.state.liquidity.supplyVault,
|
|
1258
|
+
reserveCollateralMint: reserve.state.collateral.mintPubkey,
|
|
1259
|
+
reserveCollateralTokenProgram: token_1.TOKEN_PROGRAM_ADDRESS,
|
|
1260
|
+
instructionSysvarAccount: sysvars_1.SYSVAR_INSTRUCTIONS_ADDRESS,
|
|
1261
|
+
},
|
|
1262
|
+
eventAuthority: eventAuthority,
|
|
1263
|
+
program: this._kaminoVaultProgramId,
|
|
1264
|
+
};
|
|
1265
|
+
const withdrawArgs = {
|
|
1266
|
+
sharesAmount: new bn_js_1.default(shareAmountLamports.floor().toString()),
|
|
1267
|
+
};
|
|
1268
|
+
let withdrawIxn = (0, instructions_1.withdraw)(withdrawArgs, withdrawAccounts, undefined, this._kaminoVaultProgramId);
|
|
1269
|
+
const vaultReserves = this.getVaultReserves(vaultState);
|
|
1270
|
+
withdrawIxn = this.appendRemainingAccountsForVaultReserves(withdrawIxn, vaultReserves, vaultReservesState);
|
|
1271
|
+
return withdrawIxn;
|
|
1272
|
+
}
|
|
1167
1273
|
async withdrawFromAvailableIx(user, vault, vaultState, userSharesAta, userTokenAta, shareAmountLamports) {
|
|
1168
1274
|
const globalConfig = await getKvaultGlobalConfigPda(this._kaminoVaultProgramId);
|
|
1169
1275
|
const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
|