@kamino-finance/klend-sdk 7.1.10 → 7.2.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/classes/farm_utils.d.ts +8 -0
- package/dist/classes/farm_utils.d.ts.map +1 -1
- package/dist/classes/farm_utils.js +39 -0
- package/dist/classes/farm_utils.js.map +1 -1
- package/dist/classes/manager.d.ts +52 -5
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +68 -9
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/reserve.d.ts +1 -1
- package/dist/classes/reserve.js +1 -1
- package/dist/classes/vault.d.ts +156 -10
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +477 -71
- package/dist/classes/vault.js.map +1 -1
- package/dist/manager/client_kamino_manager.js +69 -43
- package/dist/manager/client_kamino_manager.js.map +1 -1
- package/dist/utils/farmUtils.d.ts +1 -1
- package/dist/utils/farmUtils.d.ts.map +1 -1
- package/dist/utils/farmUtils.js +1 -1
- package/dist/utils/farmUtils.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/farm_utils.ts +48 -0
- package/src/classes/manager.ts +100 -14
- package/src/classes/reserve.ts +1 -1
- package/src/classes/vault.ts +677 -74
- package/src/manager/client_kamino_manager.ts +103 -44
- package/src/utils/farmUtils.ts +0 -1
package/src/classes/vault.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
Base58EncodedBytes,
|
|
8
8
|
fetchEncodedAccount,
|
|
9
9
|
generateKeyPairSigner,
|
|
10
|
-
GetAccountInfoApi,
|
|
11
10
|
getAddressEncoder,
|
|
12
11
|
getBase58Decoder,
|
|
13
12
|
GetProgramAccountsDatasizeFilter,
|
|
@@ -78,6 +77,7 @@ import { PROGRAM_ID } from '../@codegen/klend/programId';
|
|
|
78
77
|
import { ReserveWithAddress } from './reserve';
|
|
79
78
|
import { Fraction } from './fraction';
|
|
80
79
|
import {
|
|
80
|
+
CDN_ENDPOINT,
|
|
81
81
|
createAtasIdempotent,
|
|
82
82
|
createWsolAtaIfMissing,
|
|
83
83
|
getAllStandardTokenProgramTokenAccounts,
|
|
@@ -107,12 +107,13 @@ import {
|
|
|
107
107
|
} from './vault_types';
|
|
108
108
|
import { batchFetch, collToLamportsDecimal, ZERO } from '@kamino-finance/kliquidity-sdk';
|
|
109
109
|
import { FullBPSDecimal } from '@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters';
|
|
110
|
-
import { FarmIncentives, FarmState } from '@kamino-finance/farms-sdk/dist';
|
|
110
|
+
import { FarmIncentives, FarmState, getUserStatePDA } from '@kamino-finance/farms-sdk/dist';
|
|
111
111
|
import { getAccountsInLut, initLookupTableIx, insertIntoLookupTableIxs } from '../utils/lookupTable';
|
|
112
112
|
import {
|
|
113
113
|
getFarmStakeIxs,
|
|
114
114
|
getFarmUnstakeAndWithdrawIxs,
|
|
115
115
|
getSharesInFarmUserPosition,
|
|
116
|
+
getUserPendingRewardsInFarm,
|
|
116
117
|
getUserSharesInTokensStakedInFarm,
|
|
117
118
|
} from './farm_utils';
|
|
118
119
|
import { getCreateAccountInstruction, SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system';
|
|
@@ -173,6 +174,10 @@ export class KaminoVaultClient {
|
|
|
173
174
|
return this._kaminoVaultProgramId;
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
getRpc() {
|
|
178
|
+
return this._rpc;
|
|
179
|
+
}
|
|
180
|
+
|
|
176
181
|
hasFarm() {
|
|
177
182
|
return;
|
|
178
183
|
}
|
|
@@ -191,7 +196,7 @@ export class KaminoVaultClient {
|
|
|
191
196
|
return;
|
|
192
197
|
}
|
|
193
198
|
|
|
194
|
-
const kaminoVault =
|
|
199
|
+
const kaminoVault = KaminoVault.loadWithClientAndState(this, vaultPubkey, vault);
|
|
195
200
|
const vaultName = this.decodeVaultName(vault.name);
|
|
196
201
|
const slot = await this.getConnection().getSlot({ commitment: 'confirmed' }).send();
|
|
197
202
|
const tokensPerShare = await this.getTokensPerShareSingleVault(kaminoVault, slot);
|
|
@@ -203,7 +208,7 @@ export class KaminoVaultClient {
|
|
|
203
208
|
|
|
204
209
|
console.log('Name: ', vaultName);
|
|
205
210
|
console.log('Shares issued: ', sharesIssued);
|
|
206
|
-
|
|
211
|
+
holdings.print();
|
|
207
212
|
console.log('Tokens per share: ', tokensPerShare);
|
|
208
213
|
}
|
|
209
214
|
|
|
@@ -408,7 +413,7 @@ export class KaminoVaultClient {
|
|
|
408
413
|
reserveAllocationConfig: ReserveAllocationConfig,
|
|
409
414
|
vaultAdminAuthority?: TransactionSigner
|
|
410
415
|
): Promise<UpdateReserveAllocationIxs> {
|
|
411
|
-
const vaultState: VaultState = await vault.getState(
|
|
416
|
+
const vaultState: VaultState = await vault.getState();
|
|
412
417
|
const reserveState: Reserve = reserveAllocationConfig.getReserveState();
|
|
413
418
|
|
|
414
419
|
const cTokenVault = await getCTokenVaultPda(
|
|
@@ -480,7 +485,7 @@ export class KaminoVaultClient {
|
|
|
480
485
|
unallocatedWeight?: BN,
|
|
481
486
|
unallocatedCap?: BN
|
|
482
487
|
) {
|
|
483
|
-
const vaultState = await vault.getState(
|
|
488
|
+
const vaultState = await vault.getState();
|
|
484
489
|
|
|
485
490
|
const unallocatedWeightToUse = unallocatedWeight ? unallocatedWeight : vaultState.unallocatedWeight;
|
|
486
491
|
const unallocatedCapToUse = unallocatedCap ? unallocatedCap : vaultState.unallocatedTokensCap;
|
|
@@ -522,7 +527,7 @@ export class KaminoVaultClient {
|
|
|
522
527
|
reserve: Address,
|
|
523
528
|
vaultAdminAuthority?: TransactionSigner
|
|
524
529
|
): Promise<WithdrawAndBlockReserveIxs> {
|
|
525
|
-
const vaultState = await vault.getState(
|
|
530
|
+
const vaultState = await vault.getState();
|
|
526
531
|
|
|
527
532
|
const reserveIsPartOfAllocation = vaultState.vaultAllocationStrategy.some(
|
|
528
533
|
(allocation) => allocation.reserve === reserve
|
|
@@ -570,7 +575,7 @@ export class KaminoVaultClient {
|
|
|
570
575
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
571
576
|
payer?: TransactionSigner
|
|
572
577
|
): Promise<WithdrawAndBlockReserveIxs> {
|
|
573
|
-
const vaultState = await vault.getState(
|
|
578
|
+
const vaultState = await vault.getState();
|
|
574
579
|
|
|
575
580
|
const reserves = this.getVaultReserves(vaultState);
|
|
576
581
|
const withdrawAndBlockReserveIxs: WithdrawAndBlockReserveIxs = {
|
|
@@ -613,7 +618,7 @@ export class KaminoVaultClient {
|
|
|
613
618
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
614
619
|
payer?: TransactionSigner
|
|
615
620
|
): Promise<DisinvestAllReservesIxs> {
|
|
616
|
-
const vaultState = await vault.getState(
|
|
621
|
+
const vaultState = await vault.getState();
|
|
617
622
|
|
|
618
623
|
const reserves = this.getVaultReserves(vaultState);
|
|
619
624
|
const disinvestAllReservesIxs: DisinvestAllReservesIxs = {
|
|
@@ -666,7 +671,7 @@ export class KaminoVaultClient {
|
|
|
666
671
|
reserve: Address,
|
|
667
672
|
vaultAdminAuthority?: TransactionSigner
|
|
668
673
|
): Promise<Instruction | undefined> {
|
|
669
|
-
const vaultState = await vault.getState(
|
|
674
|
+
const vaultState = await vault.getState();
|
|
670
675
|
const vaultAdmin = parseVaultAdmin(vaultState, vaultAdminAuthority);
|
|
671
676
|
|
|
672
677
|
const reserveIsPartOfAllocation = vaultState.vaultAllocationStrategy.some(
|
|
@@ -700,7 +705,7 @@ export class KaminoVaultClient {
|
|
|
700
705
|
value: string,
|
|
701
706
|
vaultAdminAuthority?: TransactionSigner
|
|
702
707
|
): Promise<UpdateVaultConfigIxs> {
|
|
703
|
-
const vaultState: VaultState = await vault.getState(
|
|
708
|
+
const vaultState: VaultState = await vault.getState();
|
|
704
709
|
const admin = parseVaultAdmin(vaultState, vaultAdminAuthority);
|
|
705
710
|
|
|
706
711
|
const updateVaultConfigAccs: UpdateVaultConfigAccounts = {
|
|
@@ -802,7 +807,7 @@ export class KaminoVaultClient {
|
|
|
802
807
|
errorOnOverride: boolean = true,
|
|
803
808
|
vaultAdminAuthority?: TransactionSigner
|
|
804
809
|
): Promise<UpdateVaultConfigIxs> {
|
|
805
|
-
const vaultHasFarm = await vault.hasFarm(
|
|
810
|
+
const vaultHasFarm = await vault.hasFarm();
|
|
806
811
|
if (vaultHasFarm && errorOnOverride) {
|
|
807
812
|
throw new Error('Vault already has a farm, if you want to override it set errorOnOverride to false');
|
|
808
813
|
}
|
|
@@ -868,7 +873,7 @@ export class KaminoVaultClient {
|
|
|
868
873
|
vault: KaminoVault,
|
|
869
874
|
pendingAdmin?: TransactionSigner
|
|
870
875
|
): Promise<AcceptVaultOwnershipIxs> {
|
|
871
|
-
const vaultState: VaultState = await vault.getState(
|
|
876
|
+
const vaultState: VaultState = await vault.getState();
|
|
872
877
|
const signer = parseVaultPendingAdmin(vaultState, pendingAdmin);
|
|
873
878
|
|
|
874
879
|
const acceptOwneshipAccounts: UpdateAdminAccounts = {
|
|
@@ -929,7 +934,7 @@ export class KaminoVaultClient {
|
|
|
929
934
|
maxAmountToGiveUp: Decimal,
|
|
930
935
|
vaultAdminAuthority?: TransactionSigner
|
|
931
936
|
): Promise<Instruction> {
|
|
932
|
-
const vaultState: VaultState = await vault.getState(
|
|
937
|
+
const vaultState: VaultState = await vault.getState();
|
|
933
938
|
const vaultAdmin = parseVaultAdmin(vaultState, vaultAdminAuthority);
|
|
934
939
|
|
|
935
940
|
const giveUpPendingFeesAccounts: GiveUpPendingFeesAccounts = {
|
|
@@ -964,7 +969,7 @@ export class KaminoVaultClient {
|
|
|
964
969
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
965
970
|
vaultAdminAuthority?: TransactionSigner
|
|
966
971
|
): Promise<Instruction[]> {
|
|
967
|
-
const vaultState: VaultState = await vault.getState(
|
|
972
|
+
const vaultState: VaultState = await vault.getState();
|
|
968
973
|
const vaultAdmin = parseVaultAdmin(vaultState, vaultAdminAuthority);
|
|
969
974
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
970
975
|
const [{ ata: adminTokenAta, createAtaIx }] = await createAtasIdempotent(vaultAdmin, [
|
|
@@ -1057,7 +1062,7 @@ export class KaminoVaultClient {
|
|
|
1057
1062
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
1058
1063
|
farmState?: FarmState
|
|
1059
1064
|
): Promise<DepositIxs> {
|
|
1060
|
-
const vaultState = await vault.getState(
|
|
1065
|
+
const vaultState = await vault.getState();
|
|
1061
1066
|
|
|
1062
1067
|
const tokenProgramID = vaultState.tokenProgram;
|
|
1063
1068
|
const userTokenAta = await getAssociatedTokenAddress(vaultState.tokenMint, user.address, tokenProgramID);
|
|
@@ -1125,7 +1130,7 @@ export class KaminoVaultClient {
|
|
|
1125
1130
|
};
|
|
1126
1131
|
|
|
1127
1132
|
// if there is no farm, we can return the deposit instructions, otherwise include the stake ix in the response
|
|
1128
|
-
if (!(await vault.hasFarm(
|
|
1133
|
+
if (!(await vault.hasFarm())) {
|
|
1129
1134
|
return depositIxs;
|
|
1130
1135
|
}
|
|
1131
1136
|
|
|
@@ -1149,7 +1154,7 @@ export class KaminoVaultClient {
|
|
|
1149
1154
|
sharesAmount?: Decimal,
|
|
1150
1155
|
farmState?: FarmState
|
|
1151
1156
|
): Promise<Instruction[]> {
|
|
1152
|
-
const vaultState = await vault.getState(
|
|
1157
|
+
const vaultState = await vault.getState();
|
|
1153
1158
|
|
|
1154
1159
|
let sharesToStakeLamports = new Decimal(U64_MAX);
|
|
1155
1160
|
if (sharesAmount) {
|
|
@@ -1157,7 +1162,7 @@ export class KaminoVaultClient {
|
|
|
1157
1162
|
}
|
|
1158
1163
|
|
|
1159
1164
|
// if tokens to be staked are 0 or vault has no farm there is no stake needed
|
|
1160
|
-
if (sharesToStakeLamports.lte(0) || !(await vault.hasFarm(
|
|
1165
|
+
if (sharesToStakeLamports.lte(0) || !(await vault.hasFarm())) {
|
|
1161
1166
|
return [];
|
|
1162
1167
|
}
|
|
1163
1168
|
|
|
@@ -1183,9 +1188,8 @@ export class KaminoVaultClient {
|
|
|
1183
1188
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
1184
1189
|
farmState?: FarmState
|
|
1185
1190
|
): Promise<WithdrawIxs> {
|
|
1186
|
-
const vaultState = await vault.getState(
|
|
1187
|
-
const
|
|
1188
|
-
const hasFarm = await vault.hasFarm(this.getConnection());
|
|
1191
|
+
const vaultState = await vault.getState();
|
|
1192
|
+
const hasFarm = await vault.hasFarm();
|
|
1189
1193
|
|
|
1190
1194
|
const withdrawIxs: WithdrawIxs = {
|
|
1191
1195
|
unstakeFromFarmIfNeededIxs: [],
|
|
@@ -1262,7 +1266,7 @@ export class KaminoVaultClient {
|
|
|
1262
1266
|
if (vaultAllocation) {
|
|
1263
1267
|
const withdrawFromVaultIxs = await this.withdrawWithReserveIxs(
|
|
1264
1268
|
user,
|
|
1265
|
-
|
|
1269
|
+
vault,
|
|
1266
1270
|
sharesToWithdraw,
|
|
1267
1271
|
totalUserShares,
|
|
1268
1272
|
slot,
|
|
@@ -1270,7 +1274,7 @@ export class KaminoVaultClient {
|
|
|
1270
1274
|
);
|
|
1271
1275
|
withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
|
|
1272
1276
|
} else {
|
|
1273
|
-
const withdrawFromVaultIxs = await this.withdrawFromAvailableIxs(user,
|
|
1277
|
+
const withdrawFromVaultIxs = await this.withdrawFromAvailableIxs(user, vault, sharesToWithdraw);
|
|
1274
1278
|
withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
|
|
1275
1279
|
}
|
|
1276
1280
|
|
|
@@ -1310,8 +1314,7 @@ export class KaminoVaultClient {
|
|
|
1310
1314
|
vault: KaminoVault,
|
|
1311
1315
|
shareAmount: Decimal
|
|
1312
1316
|
): Promise<Instruction[]> {
|
|
1313
|
-
const vaultState = await vault.getState(
|
|
1314
|
-
const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
|
|
1317
|
+
const vaultState = await vault.getState();
|
|
1315
1318
|
|
|
1316
1319
|
const userSharesAta = await getAssociatedTokenAddress(vaultState.sharesMint, user.address);
|
|
1317
1320
|
const [{ ata: userTokenAta, createAtaIx }] = await createAtasIdempotent(user, [
|
|
@@ -1324,7 +1327,7 @@ export class KaminoVaultClient {
|
|
|
1324
1327
|
const shareLamportsToWithdraw = collToLamportsDecimal(shareAmount, vaultState.sharesMintDecimals.toNumber());
|
|
1325
1328
|
const withdrawFromAvailableIxn = await this.withdrawFromAvailableIx(
|
|
1326
1329
|
user,
|
|
1327
|
-
|
|
1330
|
+
vault,
|
|
1328
1331
|
vaultState,
|
|
1329
1332
|
userSharesAta,
|
|
1330
1333
|
userTokenAta,
|
|
@@ -1342,7 +1345,7 @@ export class KaminoVaultClient {
|
|
|
1342
1345
|
slot: Slot,
|
|
1343
1346
|
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
1344
1347
|
): Promise<Instruction[]> {
|
|
1345
|
-
const vaultState = await vault.getState(
|
|
1348
|
+
const vaultState = await vault.getState();
|
|
1346
1349
|
|
|
1347
1350
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
1348
1351
|
const userSharesAta = await getAssociatedTokenAddress(vaultState.sharesMint, user.address);
|
|
@@ -1463,7 +1466,7 @@ export class KaminoVaultClient {
|
|
|
1463
1466
|
vault: KaminoVault,
|
|
1464
1467
|
skipComputationChecks: boolean = false
|
|
1465
1468
|
): Promise<Instruction[]> {
|
|
1466
|
-
const vaultState = await vault.reloadState(
|
|
1469
|
+
const vaultState = await vault.reloadState();
|
|
1467
1470
|
const minInvestAmount = vaultState.minInvestAmount;
|
|
1468
1471
|
const allReserves = this.getVaultReserves(vaultState);
|
|
1469
1472
|
if (allReserves.length === 0) {
|
|
@@ -1576,7 +1579,7 @@ export class KaminoVaultClient {
|
|
|
1576
1579
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
1577
1580
|
createAtaIfNeeded: boolean = true
|
|
1578
1581
|
): Promise<Instruction[]> {
|
|
1579
|
-
const vaultState = await vault.getState(
|
|
1582
|
+
const vaultState = await vault.getState();
|
|
1580
1583
|
const cTokenVault = await getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId);
|
|
1581
1584
|
const [lendingMarketAuth] = await lendingMarketAuthPda(reserve.state.lendingMarket, this._kaminoLendProgramId);
|
|
1582
1585
|
|
|
@@ -1784,7 +1787,7 @@ export class KaminoVaultClient {
|
|
|
1784
1787
|
vault: KaminoVault,
|
|
1785
1788
|
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
1786
1789
|
): Promise<SyncVaultLUTIxs> {
|
|
1787
|
-
const vaultState = await vault.getState(
|
|
1790
|
+
const vaultState = await vault.getState();
|
|
1788
1791
|
const allAccountsToBeInserted = [
|
|
1789
1792
|
vault.address,
|
|
1790
1793
|
vaultState.vaultAdminAuthority,
|
|
@@ -1940,7 +1943,7 @@ export class KaminoVaultClient {
|
|
|
1940
1943
|
* @returns - user share balance in tokens (not lamports)
|
|
1941
1944
|
*/
|
|
1942
1945
|
async getUserSharesBalanceSingleVault(user: Address, vault: KaminoVault): Promise<UserSharesForVault> {
|
|
1943
|
-
const vaultState = await vault.getState(
|
|
1946
|
+
const vaultState = await vault.getState();
|
|
1944
1947
|
|
|
1945
1948
|
const userShares: UserSharesForVault = {
|
|
1946
1949
|
unstakedShares: new Decimal(0),
|
|
@@ -1964,7 +1967,7 @@ export class KaminoVaultClient {
|
|
|
1964
1967
|
return acc;
|
|
1965
1968
|
}, new Decimal(0));
|
|
1966
1969
|
|
|
1967
|
-
if (await vault.hasFarm(
|
|
1970
|
+
if (await vault.hasFarm()) {
|
|
1968
1971
|
const userSharesInFarm = await getUserSharesInTokensStakedInFarm(
|
|
1969
1972
|
this.getConnection(),
|
|
1970
1973
|
user,
|
|
@@ -2019,7 +2022,7 @@ export class KaminoVaultClient {
|
|
|
2019
2022
|
});
|
|
2020
2023
|
userSharesTokenAccountsPerVault.set(vault.address, userSharesTokenAccounts);
|
|
2021
2024
|
|
|
2022
|
-
if (await vault.hasFarm(
|
|
2025
|
+
if (await vault.hasFarm()) {
|
|
2023
2026
|
const userFarmState = allUserFarmStatesMap.get(state.vaultFarm);
|
|
2024
2027
|
if (userFarmState) {
|
|
2025
2028
|
console.log('there is a farm state for vault', vault.address);
|
|
@@ -2096,7 +2099,7 @@ export class KaminoVaultClient {
|
|
|
2096
2099
|
currentSlot?: Slot
|
|
2097
2100
|
): Promise<Decimal> {
|
|
2098
2101
|
// Determine if we have a KaminoVault or VaultState
|
|
2099
|
-
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState(
|
|
2102
|
+
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState() : vaultOrState;
|
|
2100
2103
|
|
|
2101
2104
|
if (vaultState.sharesIssued.isZero()) {
|
|
2102
2105
|
return new Decimal(0);
|
|
@@ -2203,7 +2206,7 @@ export class KaminoVaultClient {
|
|
|
2203
2206
|
throw Error(`kaminoVault with pubkey ${kaminoVault.address} could not be decoded`);
|
|
2204
2207
|
}
|
|
2205
2208
|
|
|
2206
|
-
return
|
|
2209
|
+
return KaminoVault.loadWithClientAndState(this, kaminoVault.address, kaminoVaultAccount);
|
|
2207
2210
|
});
|
|
2208
2211
|
}
|
|
2209
2212
|
|
|
@@ -2219,7 +2222,7 @@ export class KaminoVaultClient {
|
|
|
2219
2222
|
const vaultStates = await batchFetch(vaults, (chunk) => this.getVaultsStates(chunk));
|
|
2220
2223
|
return vaults.map((vault, index) => {
|
|
2221
2224
|
const state = vaultStates[index];
|
|
2222
|
-
return state ?
|
|
2225
|
+
return state ? KaminoVault.loadWithClientAndState(this, vault, state) : null;
|
|
2223
2226
|
});
|
|
2224
2227
|
}
|
|
2225
2228
|
|
|
@@ -2325,7 +2328,7 @@ export class KaminoVaultClient {
|
|
|
2325
2328
|
slot: Slot,
|
|
2326
2329
|
vaultReservesMap: Map<Address, KaminoReserve>
|
|
2327
2330
|
): Promise<Map<Address, Decimal>> {
|
|
2328
|
-
const vaultState = await vault.getState(
|
|
2331
|
+
const vaultState = await vault.getState();
|
|
2329
2332
|
|
|
2330
2333
|
const reserveAllocationAvailableLiquidityToWithdraw = new Map<Address, Decimal>();
|
|
2331
2334
|
vaultState.vaultAllocationStrategy.forEach((allocationStrategy) => {
|
|
@@ -2572,13 +2575,13 @@ export class KaminoVaultClient {
|
|
|
2572
2575
|
vaultReserves?: Map<Address, KaminoReserve>,
|
|
2573
2576
|
currentSlot?: Slot
|
|
2574
2577
|
): Promise<VaultHoldings> {
|
|
2575
|
-
const vaultHoldings: VaultHoldings = {
|
|
2578
|
+
const vaultHoldings: VaultHoldings = new VaultHoldings({
|
|
2576
2579
|
available: new Decimal(vault.tokenAvailable.toString()),
|
|
2577
2580
|
invested: new Decimal(0),
|
|
2578
2581
|
investedInReserves: new Map<Address, Decimal>(),
|
|
2579
2582
|
totalAUMIncludingFees: new Decimal(0),
|
|
2580
2583
|
pendingFees: new Decimal(0),
|
|
2581
|
-
};
|
|
2584
|
+
});
|
|
2582
2585
|
|
|
2583
2586
|
const currentSlotToUse = currentSlot ?? (await this.getConnection().getSlot({ commitment: 'confirmed' }).send());
|
|
2584
2587
|
const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
|
|
@@ -2643,13 +2646,13 @@ export class KaminoVaultClient {
|
|
|
2643
2646
|
const totalAvailableDecimal = lamportsToDecimal(vaultHoldings.available, decimals);
|
|
2644
2647
|
const totalInvestedDecimal = lamportsToDecimal(vaultHoldings.invested, decimals);
|
|
2645
2648
|
const pendingFees = lamportsToDecimal(totalPendingFees, decimals);
|
|
2646
|
-
return {
|
|
2649
|
+
return new VaultHoldings({
|
|
2647
2650
|
available: totalAvailableDecimal,
|
|
2648
2651
|
invested: totalInvestedDecimal,
|
|
2649
2652
|
investedInReserves: vaultHoldings.investedInReserves,
|
|
2650
2653
|
totalAUMIncludingFees: totalAvailableDecimal.add(totalInvestedDecimal),
|
|
2651
2654
|
pendingFees: pendingFees,
|
|
2652
|
-
};
|
|
2655
|
+
});
|
|
2653
2656
|
}
|
|
2654
2657
|
|
|
2655
2658
|
/**
|
|
@@ -2696,7 +2699,7 @@ export class KaminoVaultClient {
|
|
|
2696
2699
|
* @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD, along sie APYs
|
|
2697
2700
|
*/
|
|
2698
2701
|
async getVaultOverview(
|
|
2699
|
-
vault:
|
|
2702
|
+
vault: KaminoVault,
|
|
2700
2703
|
vaultTokenPrice: Decimal,
|
|
2701
2704
|
slot?: Slot,
|
|
2702
2705
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
@@ -2704,10 +2707,11 @@ export class KaminoVaultClient {
|
|
|
2704
2707
|
currentSlot?: Slot,
|
|
2705
2708
|
tokensPrices?: Map<Address, Decimal>
|
|
2706
2709
|
): Promise<VaultOverview> {
|
|
2707
|
-
const
|
|
2710
|
+
const vaultState = await vault.getState();
|
|
2711
|
+
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
2708
2712
|
|
|
2709
2713
|
const vaultHoldingsWithUSDValuePromise = this.getVaultHoldingsWithPrice(
|
|
2710
|
-
|
|
2714
|
+
vaultState,
|
|
2711
2715
|
vaultTokenPrice,
|
|
2712
2716
|
slot,
|
|
2713
2717
|
vaultReservesState,
|
|
@@ -2717,15 +2721,20 @@ export class KaminoVaultClient {
|
|
|
2717
2721
|
const slotForOverview = slot ? slot : await this.getConnection().getSlot().send();
|
|
2718
2722
|
const farmsClient = new Farms(this.getConnection());
|
|
2719
2723
|
|
|
2720
|
-
const vaultTheoreticalAPYPromise = this.getVaultTheoreticalAPY(
|
|
2721
|
-
const vaultActualAPYPromise = this.getVaultActualAPY(
|
|
2724
|
+
const vaultTheoreticalAPYPromise = this.getVaultTheoreticalAPY(vaultState, slotForOverview, vaultReservesState);
|
|
2725
|
+
const vaultActualAPYPromise = this.getVaultActualAPY(vaultState, slotForOverview, vaultReservesState);
|
|
2722
2726
|
const totalInvestedAndBorrowedPromise = this.getTotalBorrowedAndInvested(
|
|
2723
|
-
|
|
2727
|
+
vaultState,
|
|
2724
2728
|
slotForOverview,
|
|
2725
2729
|
vaultReservesState
|
|
2726
2730
|
);
|
|
2727
|
-
const vaultCollateralsPromise = this.getVaultCollaterals(
|
|
2728
|
-
|
|
2731
|
+
const vaultCollateralsPromise = this.getVaultCollaterals(
|
|
2732
|
+
vaultState,
|
|
2733
|
+
slotForOverview,
|
|
2734
|
+
vaultReservesState,
|
|
2735
|
+
kaminoMarkets
|
|
2736
|
+
);
|
|
2737
|
+
const reservesOverviewPromise = this.getVaultReservesDetails(vaultState, slotForOverview, vaultReservesState);
|
|
2729
2738
|
const vaultFarmIncentivesPromise = this.getVaultRewardsAPY(
|
|
2730
2739
|
vault,
|
|
2731
2740
|
vaultTokenPrice,
|
|
@@ -2741,6 +2750,13 @@ export class KaminoVaultClient {
|
|
|
2741
2750
|
vaultReservesState,
|
|
2742
2751
|
tokensPrices
|
|
2743
2752
|
);
|
|
2753
|
+
const vaultDelegatedFarmIncentivesPromise = this.getVaultDelegatedFarmRewardsAPY(
|
|
2754
|
+
vault,
|
|
2755
|
+
vaultTokenPrice,
|
|
2756
|
+
farmsClient,
|
|
2757
|
+
slotForOverview,
|
|
2758
|
+
tokensPrices
|
|
2759
|
+
);
|
|
2744
2760
|
|
|
2745
2761
|
// all the async part of the functions above just read the vaultReservesState which is read beforehand, so excepting vaultCollateralsPromise they should do no additional network calls
|
|
2746
2762
|
const [
|
|
@@ -2752,6 +2768,7 @@ export class KaminoVaultClient {
|
|
|
2752
2768
|
reservesOverview,
|
|
2753
2769
|
vaultFarmIncentives,
|
|
2754
2770
|
vaultReservesFarmIncentives,
|
|
2771
|
+
vaultDelegatedFarmIncentives,
|
|
2755
2772
|
] = await Promise.all([
|
|
2756
2773
|
vaultHoldingsWithUSDValuePromise,
|
|
2757
2774
|
vaultTheoreticalAPYPromise,
|
|
@@ -2761,6 +2778,7 @@ export class KaminoVaultClient {
|
|
|
2761
2778
|
reservesOverviewPromise,
|
|
2762
2779
|
vaultFarmIncentivesPromise,
|
|
2763
2780
|
vaultReservesFarmIncentivesPromise,
|
|
2781
|
+
vaultDelegatedFarmIncentivesPromise,
|
|
2764
2782
|
]);
|
|
2765
2783
|
|
|
2766
2784
|
return {
|
|
@@ -2771,6 +2789,7 @@ export class KaminoVaultClient {
|
|
|
2771
2789
|
theoreticalSupplyAPY: vaultTheoreticalAPYs,
|
|
2772
2790
|
vaultFarmIncentives: vaultFarmIncentives,
|
|
2773
2791
|
reservesFarmsIncentives: vaultReservesFarmIncentives,
|
|
2792
|
+
delegatedFarmIncentives: vaultDelegatedFarmIncentives,
|
|
2774
2793
|
totalBorrowed: totalInvestedAndBorrowed.totalBorrowed,
|
|
2775
2794
|
totalBorrowedUSD: totalInvestedAndBorrowed.totalBorrowed.mul(vaultTokenPrice),
|
|
2776
2795
|
utilizationRatio: totalInvestedAndBorrowed.utilizationRatio,
|
|
@@ -3080,11 +3099,64 @@ export class KaminoVaultClient {
|
|
|
3080
3099
|
user: Address
|
|
3081
3100
|
): Promise<ProgramDerivedAddress> {
|
|
3082
3101
|
return getProgramDerivedAddress({
|
|
3083
|
-
seeds: [addressEncoder.encode(
|
|
3102
|
+
seeds: [addressEncoder.encode(reserve), addressEncoder.encode(vault), addressEncoder.encode(user)],
|
|
3084
3103
|
programAddress: farmsProgramId,
|
|
3085
3104
|
});
|
|
3086
3105
|
}
|
|
3087
3106
|
|
|
3107
|
+
/**
|
|
3108
|
+
* Compute the delegatee PDA for the user farm state for a vault delegate farm
|
|
3109
|
+
* @param farmProgramID - the program ID of the farm program
|
|
3110
|
+
* @param vault - the address of the vault
|
|
3111
|
+
* @param farm - the address of the delegated farm
|
|
3112
|
+
* @param user - the address of the user
|
|
3113
|
+
* @returns the PDA of the delegatee user farm state for the delegated farm
|
|
3114
|
+
*/
|
|
3115
|
+
async computeUserFarmStateDelegateePDAForUserInDelegatedVaultFarm(
|
|
3116
|
+
farmProgramID: Address,
|
|
3117
|
+
vault: Address,
|
|
3118
|
+
farm: Address,
|
|
3119
|
+
user: Address
|
|
3120
|
+
): Promise<ProgramDerivedAddress> {
|
|
3121
|
+
return getProgramDerivedAddress({
|
|
3122
|
+
seeds: [addressEncoder.encode(vault), addressEncoder.encode(farm), addressEncoder.encode(user)],
|
|
3123
|
+
programAddress: farmProgramID,
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
/**
|
|
3128
|
+
* Compute the user state PDA for a user in a delegated vault farm
|
|
3129
|
+
* @param farmProgramID - the program ID of the farm program
|
|
3130
|
+
* @param vault - the address of the vault
|
|
3131
|
+
* @param farm - the address of the delegated farm
|
|
3132
|
+
* @param user - the address of the user
|
|
3133
|
+
* @returns the PDA of the user state for the delegated farm
|
|
3134
|
+
*/
|
|
3135
|
+
async computeUserStatePDAForUserInDelegatedVaultFarm(
|
|
3136
|
+
farmProgramID: Address,
|
|
3137
|
+
vault: Address,
|
|
3138
|
+
farm: Address,
|
|
3139
|
+
user: Address
|
|
3140
|
+
): Promise<Address> {
|
|
3141
|
+
const delegateePDA = await this.computeDelegateeForUserInDelegatedFarm(farmProgramID, vault, farm, user);
|
|
3142
|
+
return getUserStatePDA(farmProgramID, farm, delegateePDA);
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
async computeDelegateeForUserInDelegatedFarm(
|
|
3146
|
+
farmProgramID: Address,
|
|
3147
|
+
vault: Address,
|
|
3148
|
+
farm: Address,
|
|
3149
|
+
user: Address
|
|
3150
|
+
): Promise<Address> {
|
|
3151
|
+
const delegateePDA = await this.computeUserFarmStateDelegateePDAForUserInDelegatedVaultFarm(
|
|
3152
|
+
farmProgramID,
|
|
3153
|
+
vault,
|
|
3154
|
+
farm,
|
|
3155
|
+
user
|
|
3156
|
+
);
|
|
3157
|
+
return delegateePDA[0];
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3088
3160
|
/**
|
|
3089
3161
|
* Read the APY of the farm built on top of the vault (farm in vaultState.vaultFarm)
|
|
3090
3162
|
* @param vault - the vault to read the farm APY for
|
|
@@ -3101,7 +3173,7 @@ export class KaminoVaultClient {
|
|
|
3101
3173
|
tokensPrices?: Map<Address, Decimal>
|
|
3102
3174
|
): Promise<FarmIncentives> {
|
|
3103
3175
|
// Determine if we have a KaminoVault or VaultState
|
|
3104
|
-
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState(
|
|
3176
|
+
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState() : vaultOrState;
|
|
3105
3177
|
if (vaultState.vaultFarm === DEFAULT_PUBLIC_KEY) {
|
|
3106
3178
|
return {
|
|
3107
3179
|
incentivesStats: [],
|
|
@@ -3117,6 +3189,39 @@ export class KaminoVaultClient {
|
|
|
3117
3189
|
return getFarmIncentives(kFarmsClient, vaultState.vaultFarm, sharePrice, stakedTokenMintDecimals, tokensPrices);
|
|
3118
3190
|
}
|
|
3119
3191
|
|
|
3192
|
+
/**
|
|
3193
|
+
* Read the APY of the delegated farm providing incentives for vault depositors
|
|
3194
|
+
* @param vault - the vault to read the farm APY for
|
|
3195
|
+
* @param vaultTokenPrice - the price of the vault token in USD (e.g. 1.0 for USDC)
|
|
3196
|
+
* @param [farmsClient] - the farms client to use. Optional. If not provided, the function will create a new one
|
|
3197
|
+
* @param [slot] - the slot to read the farm APY for. Optional. If not provided, the function will read the current slot
|
|
3198
|
+
* @param [tokensPrices] - the prices of the tokens in USD. Optional. If not provided, the function will fetch the prices
|
|
3199
|
+
* @returns the APY of the delegated farm providing incentives for vault depositors
|
|
3200
|
+
*/
|
|
3201
|
+
async getVaultDelegatedFarmRewardsAPY(
|
|
3202
|
+
vault: KaminoVault,
|
|
3203
|
+
vaultTokenPrice: Decimal,
|
|
3204
|
+
farmsClient?: Farms,
|
|
3205
|
+
slot?: Slot,
|
|
3206
|
+
tokensPrices?: Map<Address, Decimal>
|
|
3207
|
+
): Promise<FarmIncentives> {
|
|
3208
|
+
const delegatedFarm = await this.getDelegatedFarmForVault(vault.address);
|
|
3209
|
+
if (!delegatedFarm) {
|
|
3210
|
+
return {
|
|
3211
|
+
incentivesStats: [],
|
|
3212
|
+
totalIncentivesApy: 0,
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
const vaultState = await vault.getState();
|
|
3217
|
+
const tokensPerShare = await this.getTokensPerShareSingleVault(vaultState, slot);
|
|
3218
|
+
const sharePrice = tokensPerShare.mul(vaultTokenPrice);
|
|
3219
|
+
const stakedTokenMintDecimals = vaultState.sharesMintDecimals.toNumber();
|
|
3220
|
+
|
|
3221
|
+
const kFarmsClient = farmsClient ? farmsClient : new Farms(this.getConnection());
|
|
3222
|
+
return getFarmIncentives(kFarmsClient, delegatedFarm, sharePrice, stakedTokenMintDecimals, tokensPrices);
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3120
3225
|
/**
|
|
3121
3226
|
* Get all the token mints of the vault, vault farm rewards and the allocation rewards
|
|
3122
3227
|
* @param vaults - the vaults to get the token mints for
|
|
@@ -3137,9 +3242,9 @@ export class KaminoVaultClient {
|
|
|
3137
3242
|
const reservesToFetch = new Set<Address>();
|
|
3138
3243
|
|
|
3139
3244
|
for (const vault of vaults) {
|
|
3140
|
-
const vaultState = await vault.getState(
|
|
3245
|
+
const vaultState = await vault.getState();
|
|
3141
3246
|
vaultsTokenMints.add(vaultState.tokenMint);
|
|
3142
|
-
const hasFarm = await vault.hasFarm(
|
|
3247
|
+
const hasFarm = await vault.hasFarm();
|
|
3143
3248
|
if (hasFarm) {
|
|
3144
3249
|
const farmAddress = vaultState.vaultFarm;
|
|
3145
3250
|
if (!kFarmsMap.has(farmAddress)) {
|
|
@@ -3225,10 +3330,10 @@ export class KaminoVaultClient {
|
|
|
3225
3330
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
3226
3331
|
tokensPrices?: Map<Address, Decimal>
|
|
3227
3332
|
): Promise<VaultReservesFarmsIncentives> {
|
|
3228
|
-
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState(
|
|
3333
|
+
const vaultState = 'getState' in vaultOrState ? await vaultOrState.getState() : vaultOrState;
|
|
3229
3334
|
|
|
3230
3335
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
3231
|
-
const currentSlot = slot
|
|
3336
|
+
const currentSlot = slot ?? (await this.getConnection().getSlot({ commitment: 'confirmed' }).send());
|
|
3232
3337
|
|
|
3233
3338
|
const holdings = await this.getVaultHoldings(vaultState, currentSlot, vaultReservesState);
|
|
3234
3339
|
|
|
@@ -3264,7 +3369,6 @@ export class KaminoVaultClient {
|
|
|
3264
3369
|
kFarmsClient,
|
|
3265
3370
|
currentSlot,
|
|
3266
3371
|
reserveState.state,
|
|
3267
|
-
undefined,
|
|
3268
3372
|
tokensPrices
|
|
3269
3373
|
);
|
|
3270
3374
|
vaultReservesFarmsIncentives.set(reserveAddress, reserveFarmIncentives.collateralFarmIncentives);
|
|
@@ -3282,6 +3386,323 @@ export class KaminoVaultClient {
|
|
|
3282
3386
|
};
|
|
3283
3387
|
}
|
|
3284
3388
|
|
|
3389
|
+
/// reads the pending rewards for a user in the vault farm
|
|
3390
|
+
/// @param user - the user address
|
|
3391
|
+
/// @param vault - the vault
|
|
3392
|
+
/// @returns a map of the pending rewards token mint and amount in lamports
|
|
3393
|
+
async getUserPendingRewardsInVaultFarm(user: Address, vault: KaminoVault): Promise<Map<Address, Decimal>> {
|
|
3394
|
+
const vaultState = await vault.getState();
|
|
3395
|
+
const hasFarm = await vault.hasFarm();
|
|
3396
|
+
if (!hasFarm) {
|
|
3397
|
+
return new Map<Address, Decimal>();
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
const farmClient = new Farms(this.getConnection());
|
|
3401
|
+
const userState = await getUserStatePDA(farmClient.getProgramID(), vaultState.vaultFarm, user);
|
|
3402
|
+
return getUserPendingRewardsInFarm(this.getConnection(), userState, vaultState.vaultFarm);
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3405
|
+
/// reads the pending rewards for a user in a delegated vault farm
|
|
3406
|
+
/// @param user - the user address
|
|
3407
|
+
/// @param vaultAddress - the address of the vault
|
|
3408
|
+
/// @returns a map of the pending rewards token mint and amount in lamports
|
|
3409
|
+
async getUserPendingRewardsInVaultDelegatedFarm(
|
|
3410
|
+
user: Address,
|
|
3411
|
+
vaultAddress: Address
|
|
3412
|
+
): Promise<Map<Address, Decimal>> {
|
|
3413
|
+
const delegatedFarm = await this.getDelegatedFarmForVault(vaultAddress);
|
|
3414
|
+
if (!delegatedFarm) {
|
|
3415
|
+
return new Map<Address, Decimal>();
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
const farmClient = new Farms(this.getConnection());
|
|
3419
|
+
const userState = await this.computeUserStatePDAForUserInDelegatedVaultFarm(
|
|
3420
|
+
farmClient.getProgramID(),
|
|
3421
|
+
vaultAddress,
|
|
3422
|
+
delegatedFarm,
|
|
3423
|
+
user
|
|
3424
|
+
);
|
|
3425
|
+
|
|
3426
|
+
return getUserPendingRewardsInFarm(this.getConnection(), userState, delegatedFarm);
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
/// gets the delegated farm for a vault
|
|
3430
|
+
async getDelegatedFarmForVault(vault: Address): Promise<Address | undefined> {
|
|
3431
|
+
const response = await fetch(`${CDN_ENDPOINT}/resources.json`);
|
|
3432
|
+
if (!response.ok) {
|
|
3433
|
+
console.log(`Failed to fetch CDN for user pending rewards in vault delegated farm: ${response.statusText}`);
|
|
3434
|
+
return undefined;
|
|
3435
|
+
}
|
|
3436
|
+
const data = (await response.json()) as { 'mainnet-beta'?: { delegatedVaultFarms: any } };
|
|
3437
|
+
const delegatedVaultFarms = data['mainnet-beta']?.delegatedVaultFarms;
|
|
3438
|
+
if (!delegatedVaultFarms) {
|
|
3439
|
+
return undefined;
|
|
3440
|
+
}
|
|
3441
|
+
const delegatedFarmWithVault = delegatedVaultFarms.find((vaultWithFarm: any) => vaultWithFarm.vault === vault);
|
|
3442
|
+
if (!delegatedFarmWithVault) {
|
|
3443
|
+
return undefined;
|
|
3444
|
+
}
|
|
3445
|
+
return address(delegatedFarmWithVault.farm);
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
/// reads the pending rewards for a user in the reserves farms of a vault
|
|
3449
|
+
/// @param user - the user address
|
|
3450
|
+
/// @param vault - the vault
|
|
3451
|
+
/// @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
3452
|
+
/// @returns a map of the pending rewards token mint and amount in lamports
|
|
3453
|
+
async getUserPendingRewardsInVaultReservesFarms(
|
|
3454
|
+
user: Address,
|
|
3455
|
+
vault: KaminoVault,
|
|
3456
|
+
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
3457
|
+
): Promise<Map<Address, Decimal>> {
|
|
3458
|
+
const vaultState = await vault.getState();
|
|
3459
|
+
|
|
3460
|
+
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
3461
|
+
|
|
3462
|
+
const vaultReserves = vaultState.vaultAllocationStrategy
|
|
3463
|
+
.map((allocationStrategy) => allocationStrategy.reserve)
|
|
3464
|
+
.filter((reserve) => reserve !== DEFAULT_PUBLIC_KEY);
|
|
3465
|
+
const pendingRewardsPerToken: Map<Address, Decimal> = new Map();
|
|
3466
|
+
|
|
3467
|
+
const farmClient = new Farms(this.getConnection());
|
|
3468
|
+
for (const reserveAddress of vaultReserves) {
|
|
3469
|
+
const reserveState = vaultReservesState.get(reserveAddress);
|
|
3470
|
+
if (!reserveState) {
|
|
3471
|
+
console.log(`Reserve to read farm incentives for not found: ${reserveAddress}`);
|
|
3472
|
+
continue;
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
if (reserveState.state.farmCollateral === DEFAULT_PUBLIC_KEY) {
|
|
3476
|
+
continue;
|
|
3477
|
+
}
|
|
3478
|
+
|
|
3479
|
+
const delegatee = await this.computeUserFarmStateDelegateePDAForUserInVault(
|
|
3480
|
+
farmClient.getProgramID(),
|
|
3481
|
+
vault.address,
|
|
3482
|
+
reserveAddress,
|
|
3483
|
+
user
|
|
3484
|
+
);
|
|
3485
|
+
const userState = await getUserStatePDA(
|
|
3486
|
+
farmClient.getProgramID(),
|
|
3487
|
+
reserveState.state.farmCollateral,
|
|
3488
|
+
delegatee[0]
|
|
3489
|
+
);
|
|
3490
|
+
const pendingRewards = await getUserPendingRewardsInFarm(
|
|
3491
|
+
this.getConnection(),
|
|
3492
|
+
userState,
|
|
3493
|
+
reserveState.state.farmCollateral
|
|
3494
|
+
);
|
|
3495
|
+
pendingRewards.forEach((reward, token) => {
|
|
3496
|
+
const existingReward = pendingRewardsPerToken.get(token);
|
|
3497
|
+
if (existingReward) {
|
|
3498
|
+
pendingRewardsPerToken.set(token, existingReward.add(reward));
|
|
3499
|
+
} else {
|
|
3500
|
+
pendingRewardsPerToken.set(token, reward);
|
|
3501
|
+
}
|
|
3502
|
+
});
|
|
3503
|
+
}
|
|
3504
|
+
|
|
3505
|
+
return pendingRewardsPerToken;
|
|
3506
|
+
}
|
|
3507
|
+
|
|
3508
|
+
/// reads the pending rewards for a user in the vault farm, the reserves farms of the vault and the delegated vault farm
|
|
3509
|
+
/// @param user - the user address
|
|
3510
|
+
/// @param vault - the vault
|
|
3511
|
+
/// @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
3512
|
+
/// @returns a struct containing the pending rewards in the vault farm, the reserves farms of the vault and the delegated vault farm, and the total pending rewards in lamports
|
|
3513
|
+
async getAllPendingRewardsForUserInVault(
|
|
3514
|
+
user: Address,
|
|
3515
|
+
vault: KaminoVault,
|
|
3516
|
+
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
3517
|
+
): Promise<PendingRewardsForUserInVault> {
|
|
3518
|
+
const pendingRewardsInVaultFarm = await this.getUserPendingRewardsInVaultFarm(user, vault);
|
|
3519
|
+
const pendingRewardsInVaultReservesFarms = await this.getUserPendingRewardsInVaultReservesFarms(
|
|
3520
|
+
user,
|
|
3521
|
+
vault,
|
|
3522
|
+
vaultReservesMap
|
|
3523
|
+
);
|
|
3524
|
+
const pendingRewardsInVaultDelegatedFarm = await this.getUserPendingRewardsInVaultDelegatedFarm(
|
|
3525
|
+
user,
|
|
3526
|
+
vault.address
|
|
3527
|
+
);
|
|
3528
|
+
|
|
3529
|
+
const totalPendingRewards = new Map<Address, Decimal>();
|
|
3530
|
+
pendingRewardsInVaultFarm.forEach((reward, token) => {
|
|
3531
|
+
const existingReward = totalPendingRewards.get(token);
|
|
3532
|
+
if (existingReward) {
|
|
3533
|
+
totalPendingRewards.set(token, existingReward.add(reward));
|
|
3534
|
+
} else {
|
|
3535
|
+
totalPendingRewards.set(token, reward);
|
|
3536
|
+
}
|
|
3537
|
+
});
|
|
3538
|
+
pendingRewardsInVaultReservesFarms.forEach((reward, token) => {
|
|
3539
|
+
const existingReward = totalPendingRewards.get(token);
|
|
3540
|
+
if (existingReward) {
|
|
3541
|
+
totalPendingRewards.set(token, existingReward.add(reward));
|
|
3542
|
+
} else {
|
|
3543
|
+
totalPendingRewards.set(token, reward);
|
|
3544
|
+
}
|
|
3545
|
+
});
|
|
3546
|
+
pendingRewardsInVaultDelegatedFarm.forEach((reward, token) => {
|
|
3547
|
+
const existingReward = totalPendingRewards.get(token);
|
|
3548
|
+
if (existingReward) {
|
|
3549
|
+
totalPendingRewards.set(token, existingReward.add(reward));
|
|
3550
|
+
} else {
|
|
3551
|
+
totalPendingRewards.set(token, reward);
|
|
3552
|
+
}
|
|
3553
|
+
});
|
|
3554
|
+
|
|
3555
|
+
return {
|
|
3556
|
+
pendingRewardsInVaultFarm,
|
|
3557
|
+
pendingRewardsInVaultReservesFarms,
|
|
3558
|
+
pendingRewardsInVaultDelegatedFarm,
|
|
3559
|
+
totalPendingRewards,
|
|
3560
|
+
};
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
/**
|
|
3564
|
+
* This function will return the instructions to claim the rewards for the farm of a vault, the delegated farm of the vault and the reserves farms of the vault
|
|
3565
|
+
* @param user - the user to claim the rewards
|
|
3566
|
+
* @param vault - the vault
|
|
3567
|
+
* @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
3568
|
+
* @returns the instructions to claim the rewards for the farm of the vault, the delegated farm of the vault and the reserves farms of the vault
|
|
3569
|
+
*/
|
|
3570
|
+
async getClaimAllRewardsForVaultIxs(
|
|
3571
|
+
user: TransactionSigner,
|
|
3572
|
+
vault: KaminoVault,
|
|
3573
|
+
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
3574
|
+
): Promise<Instruction[]> {
|
|
3575
|
+
const [vaultFarmIxs, delegatedFarmIxs, reservesFarmsIxs] = await Promise.all([
|
|
3576
|
+
this.getClaimVaultFarmRewardsIxs(user, vault),
|
|
3577
|
+
this.getClaimVaultDelegatedFarmRewardsIxs(user, vault),
|
|
3578
|
+
this.getClaimVaultReservesFarmsRewardsIxs(user, vault, vaultReservesMap),
|
|
3579
|
+
]);
|
|
3580
|
+
|
|
3581
|
+
return [...new Set([...vaultFarmIxs, ...delegatedFarmIxs, ...reservesFarmsIxs])];
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
/**
|
|
3585
|
+
* This function will return the instructions to claim the rewards for the farm of a vault
|
|
3586
|
+
* @param user - the user to claim the rewards
|
|
3587
|
+
* @param vault - the vault
|
|
3588
|
+
* @returns the instructions to claim the rewards for the farm of the vault
|
|
3589
|
+
*/
|
|
3590
|
+
async getClaimVaultFarmRewardsIxs(user: TransactionSigner, vault: KaminoVault): Promise<Instruction[]> {
|
|
3591
|
+
const vaultState = await vault.getState();
|
|
3592
|
+
const hasFarm = await vault.hasFarm();
|
|
3593
|
+
if (!hasFarm) {
|
|
3594
|
+
return [];
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
const farmClient = new Farms(this.getConnection());
|
|
3598
|
+
const pendingRewardsInVaultFarm = await this.getUserPendingRewardsInVaultFarm(user.address, vault);
|
|
3599
|
+
// if there are no pending rewards of their total is 0 no ix is needed
|
|
3600
|
+
const totalPendingRewards = Array.from(pendingRewardsInVaultFarm.values()).reduce(
|
|
3601
|
+
(acc, reward) => acc.add(reward),
|
|
3602
|
+
new Decimal(0)
|
|
3603
|
+
);
|
|
3604
|
+
if (totalPendingRewards.eq(0)) {
|
|
3605
|
+
return [];
|
|
3606
|
+
}
|
|
3607
|
+
return farmClient.claimForUserForFarmAllRewardsIx(user, vaultState.vaultFarm, false);
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
/**
|
|
3611
|
+
* This function will return the instructions to claim the rewards for the delegated farm of a vault
|
|
3612
|
+
* @param user - the user to claim the rewards
|
|
3613
|
+
* @param vault - the vault
|
|
3614
|
+
* @returns the instructions to claim the rewards for the delegated farm of the vault
|
|
3615
|
+
*/
|
|
3616
|
+
async getClaimVaultDelegatedFarmRewardsIxs(user: TransactionSigner, vault: KaminoVault): Promise<Instruction[]> {
|
|
3617
|
+
const delegatedFarm = await this.getDelegatedFarmForVault(vault.address);
|
|
3618
|
+
if (!delegatedFarm) {
|
|
3619
|
+
return [];
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
const farmClient = new Farms(this.getConnection());
|
|
3623
|
+
|
|
3624
|
+
const delegatee = await this.computeDelegateeForUserInDelegatedFarm(
|
|
3625
|
+
farmClient.getProgramID(),
|
|
3626
|
+
vault.address,
|
|
3627
|
+
delegatedFarm,
|
|
3628
|
+
user.address
|
|
3629
|
+
);
|
|
3630
|
+
const userState = await getUserStatePDA(farmClient.getProgramID(), delegatedFarm, delegatee);
|
|
3631
|
+
// check if the user state exists
|
|
3632
|
+
const userStateExists = await fetchEncodedAccount(this.getConnection(), userState);
|
|
3633
|
+
if (!userStateExists.exists) {
|
|
3634
|
+
return [];
|
|
3635
|
+
}
|
|
3636
|
+
|
|
3637
|
+
return farmClient.claimForUserForFarmAllRewardsIx(user, delegatedFarm, true, [delegatee]);
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3640
|
+
/**
|
|
3641
|
+
* This function will return the instructions to claim the rewards for the reserves farms of a vault
|
|
3642
|
+
* @param user - the user to claim the rewards
|
|
3643
|
+
* @param vault - the vault
|
|
3644
|
+
* @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
3645
|
+
* @returns the instructions to claim the rewards for the reserves farms of the vault
|
|
3646
|
+
*/
|
|
3647
|
+
async getClaimVaultReservesFarmsRewardsIxs(
|
|
3648
|
+
user: TransactionSigner,
|
|
3649
|
+
vault: KaminoVault,
|
|
3650
|
+
vaultReservesMap?: Map<Address, KaminoReserve>
|
|
3651
|
+
): Promise<Instruction[]> {
|
|
3652
|
+
const vaultState = await vault.getState();
|
|
3653
|
+
|
|
3654
|
+
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
3655
|
+
|
|
3656
|
+
const vaultReserves = vaultState.vaultAllocationStrategy
|
|
3657
|
+
.map((allocationStrategy) => allocationStrategy.reserve)
|
|
3658
|
+
.filter((reserve) => reserve !== DEFAULT_PUBLIC_KEY);
|
|
3659
|
+
|
|
3660
|
+
const ixs: Instruction[] = [];
|
|
3661
|
+
const farmClient = new Farms(this.getConnection());
|
|
3662
|
+
for (const reserveAddress of vaultReserves) {
|
|
3663
|
+
const reserveState = vaultReservesState.get(reserveAddress);
|
|
3664
|
+
if (!reserveState) {
|
|
3665
|
+
console.log(`Reserve to read farm incentives for not found: ${reserveAddress}`);
|
|
3666
|
+
continue;
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
if (reserveState.state.farmCollateral === DEFAULT_PUBLIC_KEY) {
|
|
3670
|
+
continue;
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
const delegatee = await this.computeUserFarmStateDelegateePDAForUserInVault(
|
|
3674
|
+
farmClient.getProgramID(),
|
|
3675
|
+
vault.address,
|
|
3676
|
+
reserveAddress,
|
|
3677
|
+
user.address
|
|
3678
|
+
);
|
|
3679
|
+
const userState = await getUserStatePDA(
|
|
3680
|
+
farmClient.getProgramID(),
|
|
3681
|
+
reserveState.state.farmCollateral,
|
|
3682
|
+
delegatee[0]
|
|
3683
|
+
);
|
|
3684
|
+
|
|
3685
|
+
const pendingRewards = await getUserPendingRewardsInFarm(
|
|
3686
|
+
this.getConnection(),
|
|
3687
|
+
userState,
|
|
3688
|
+
reserveState.state.farmCollateral
|
|
3689
|
+
);
|
|
3690
|
+
const totalPendingRewards = Array.from(pendingRewards.values()).reduce(
|
|
3691
|
+
(acc, reward) => acc.add(reward),
|
|
3692
|
+
new Decimal(0)
|
|
3693
|
+
);
|
|
3694
|
+
if (totalPendingRewards.eq(0)) {
|
|
3695
|
+
continue;
|
|
3696
|
+
}
|
|
3697
|
+
const ix = await farmClient.claimForUserForFarmAllRewardsIx(user, reserveState.state.farmCollateral, true, [
|
|
3698
|
+
delegatee[0],
|
|
3699
|
+
]);
|
|
3700
|
+
ixs.push(...ix);
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
return ixs;
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3285
3706
|
private appendRemainingAccountsForVaultReserves(
|
|
3286
3707
|
ix: Instruction,
|
|
3287
3708
|
vaultReserves: Address[],
|
|
@@ -3310,16 +3731,33 @@ export class KaminoVault {
|
|
|
3310
3731
|
readonly address: Address;
|
|
3311
3732
|
state: VaultState | undefined | null;
|
|
3312
3733
|
programId: Address;
|
|
3734
|
+
client: KaminoVaultClient;
|
|
3735
|
+
vaultReservesStateCache: Map<Address, KaminoReserve> | undefined;
|
|
3313
3736
|
|
|
3314
|
-
constructor(
|
|
3737
|
+
constructor(
|
|
3738
|
+
rpc: Rpc<SolanaRpcApi>,
|
|
3739
|
+
vaultAddress: Address,
|
|
3740
|
+
state?: VaultState,
|
|
3741
|
+
programId: Address = kaminoVaultId,
|
|
3742
|
+
recentSlotDurationMs: number = DEFAULT_RECENT_SLOT_DURATION_MS
|
|
3743
|
+
) {
|
|
3315
3744
|
this.address = vaultAddress;
|
|
3316
3745
|
this.state = state;
|
|
3317
3746
|
this.programId = programId;
|
|
3747
|
+
this.client = new KaminoVaultClient(rpc, recentSlotDurationMs);
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3750
|
+
static loadWithClientAndState(client: KaminoVaultClient, vaultAddress: Address, state: VaultState): KaminoVault {
|
|
3751
|
+
const vault = new KaminoVault(client.getConnection(), vaultAddress);
|
|
3752
|
+
vault.state = state;
|
|
3753
|
+
vault.programId = client.getProgramID();
|
|
3754
|
+
vault.client = client;
|
|
3755
|
+
return vault;
|
|
3318
3756
|
}
|
|
3319
3757
|
|
|
3320
|
-
async getState(
|
|
3758
|
+
async getState(): Promise<VaultState> {
|
|
3321
3759
|
if (!this.state) {
|
|
3322
|
-
const res = await VaultState.fetch(
|
|
3760
|
+
const res = await VaultState.fetch(this.client.getConnection(), this.address, this.programId);
|
|
3323
3761
|
if (!res) {
|
|
3324
3762
|
throw new Error('Invalid vault');
|
|
3325
3763
|
}
|
|
@@ -3330,18 +3768,141 @@ export class KaminoVault {
|
|
|
3330
3768
|
}
|
|
3331
3769
|
}
|
|
3332
3770
|
|
|
3333
|
-
async
|
|
3334
|
-
this.
|
|
3771
|
+
async reloadVaultReserves(): Promise<void> {
|
|
3772
|
+
this.vaultReservesStateCache = await this.client.loadVaultReserves(this.state!);
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
async reloadState(): Promise<VaultState> {
|
|
3776
|
+
this.state = await VaultState.fetch(this.client.getConnection(), this.address, this.programId);
|
|
3335
3777
|
if (!this.state) {
|
|
3336
3778
|
throw new Error('Could not fetch vault');
|
|
3337
3779
|
}
|
|
3338
3780
|
return this.state;
|
|
3339
3781
|
}
|
|
3340
3782
|
|
|
3341
|
-
async hasFarm(
|
|
3342
|
-
const state = await this.getState(
|
|
3783
|
+
async hasFarm(): Promise<boolean> {
|
|
3784
|
+
const state = await this.getState();
|
|
3343
3785
|
return state.vaultFarm !== DEFAULT_PUBLIC_KEY;
|
|
3344
3786
|
}
|
|
3787
|
+
|
|
3788
|
+
/**
|
|
3789
|
+
* This will return an VaultHoldings object which contains the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve
|
|
3790
|
+
* @returns an VaultHoldings object representing the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve
|
|
3791
|
+
*/
|
|
3792
|
+
async getVaultHoldings(): Promise<VaultHoldings> {
|
|
3793
|
+
if (!this.state || !this.vaultReservesStateCache) {
|
|
3794
|
+
await this.reloadState();
|
|
3795
|
+
await this.reloadVaultReserves();
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3798
|
+
return await this.client.getVaultHoldings(this.state!, undefined, this.vaultReservesStateCache!, undefined);
|
|
3799
|
+
}
|
|
3800
|
+
|
|
3801
|
+
/**
|
|
3802
|
+
* This will return the a map between reserve pubkey and the allocation overview for the reserve
|
|
3803
|
+
* @returns a map between reserve pubkey and the allocation overview for the reserve
|
|
3804
|
+
*/
|
|
3805
|
+
async getVaultAllocations(): Promise<Map<Address, ReserveAllocationOverview>> {
|
|
3806
|
+
if (!this.state) {
|
|
3807
|
+
await this.reloadState();
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3810
|
+
return this.client.getVaultAllocations(this.state!);
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
/**
|
|
3814
|
+
* This will return the APY of the vault based on the current invested amounts and the theoretical APY if all the available tokens were invested
|
|
3815
|
+
* @returns a struct containing actualAPY and theoreticalAPY for the vault
|
|
3816
|
+
*/
|
|
3817
|
+
async getAPYs(slot?: Slot): Promise<VaultAPYs> {
|
|
3818
|
+
if (!this.state || !this.vaultReservesStateCache) {
|
|
3819
|
+
await this.reloadState();
|
|
3820
|
+
await this.reloadVaultReserves();
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
const latestSlot = slot ?? (await this.client.getConnection().getSlot({ commitment: 'confirmed' }).send());
|
|
3824
|
+
const actualApy = await this.client.getVaultActualAPY(this.state!, latestSlot, this.vaultReservesStateCache!);
|
|
3825
|
+
const theoreticalApy = await this.client.getVaultTheoreticalAPY(
|
|
3826
|
+
this.state!,
|
|
3827
|
+
latestSlot,
|
|
3828
|
+
this.vaultReservesStateCache!
|
|
3829
|
+
);
|
|
3830
|
+
|
|
3831
|
+
return {
|
|
3832
|
+
actualAPY: actualApy,
|
|
3833
|
+
theoreticalAPY: theoreticalApy,
|
|
3834
|
+
};
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
/**
|
|
3838
|
+
* This method returns the exchange rate of the vault (tokens per share)
|
|
3839
|
+
* @returns - Decimal representing the exchange rate (tokens per share)
|
|
3840
|
+
*/
|
|
3841
|
+
async getExchangeRate(slot?: Slot): Promise<Decimal> {
|
|
3842
|
+
if (!this.state || !this.vaultReservesStateCache) {
|
|
3843
|
+
await this.reloadState();
|
|
3844
|
+
await this.reloadVaultReserves();
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
const latestSlot = slot ?? (await this.client.getConnection().getSlot({ commitment: 'confirmed' }).send());
|
|
3848
|
+
const tokensPerShare = await this.client.getTokensPerShareSingleVault(this.state!, latestSlot);
|
|
3849
|
+
return tokensPerShare;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
/**
|
|
3853
|
+
* This method returns the user shares balance for a given vault
|
|
3854
|
+
* @param user - user to calculate the shares balance for
|
|
3855
|
+
* @param vault - vault to calculate shares balance for
|
|
3856
|
+
* @returns - a struct of user share balance (staked in vault farm if the vault has a farm and unstaked) in decimal (not lamports)
|
|
3857
|
+
*/
|
|
3858
|
+
async getUserShares(user: Address): Promise<UserSharesForVault> {
|
|
3859
|
+
return this.client.getUserSharesBalanceSingleVault(user, this);
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
/**
|
|
3863
|
+
* This function creates instructions to deposit into a vault. It will also create ATA creation instructions for the vault shares that the user receives in return
|
|
3864
|
+
* @param user - user to deposit
|
|
3865
|
+
* @param tokenAmount - token amount to be deposited, in decimals (will be converted in lamports)
|
|
3866
|
+
* @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
|
|
3867
|
+
* @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
|
|
3868
|
+
* @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
|
|
3869
|
+
*/
|
|
3870
|
+
async depositIxs(
|
|
3871
|
+
user: TransactionSigner,
|
|
3872
|
+
tokenAmount: Decimal,
|
|
3873
|
+
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
3874
|
+
farmState?: FarmState
|
|
3875
|
+
): Promise<DepositIxs> {
|
|
3876
|
+
if (vaultReservesMap) {
|
|
3877
|
+
this.vaultReservesStateCache = vaultReservesMap;
|
|
3878
|
+
}
|
|
3879
|
+
return this.client.depositIxs(user, this, tokenAmount, this.vaultReservesStateCache, farmState);
|
|
3880
|
+
}
|
|
3881
|
+
|
|
3882
|
+
/**
|
|
3883
|
+
* 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
|
|
3884
|
+
* @param user - user to withdraw
|
|
3885
|
+
* @param shareAmount - share amount to withdraw (in tokens, not lamports), in order to withdraw everything, any value > user share amount
|
|
3886
|
+
* @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
|
|
3887
|
+
* @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
|
|
3888
|
+
* @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
|
|
3889
|
+
* @returns an array of instructions to create missing ATAs if needed and the withdraw instructions
|
|
3890
|
+
*/
|
|
3891
|
+
async withdrawIxs(
|
|
3892
|
+
user: TransactionSigner,
|
|
3893
|
+
shareAmount: Decimal,
|
|
3894
|
+
slot?: Slot,
|
|
3895
|
+
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
3896
|
+
farmState?: FarmState
|
|
3897
|
+
): Promise<WithdrawIxs> {
|
|
3898
|
+
if (vaultReservesMap) {
|
|
3899
|
+
this.vaultReservesStateCache = vaultReservesMap;
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3902
|
+
const currentSlot = slot ?? (await this.client.getConnection().getSlot({ commitment: 'confirmed' }).send());
|
|
3903
|
+
|
|
3904
|
+
return this.client.withdrawIxs(user, this, shareAmount, currentSlot, this.vaultReservesStateCache, farmState);
|
|
3905
|
+
}
|
|
3345
3906
|
}
|
|
3346
3907
|
|
|
3347
3908
|
/**
|
|
@@ -3456,13 +4017,56 @@ export type VaultHolder = {
|
|
|
3456
4017
|
amount: Decimal;
|
|
3457
4018
|
};
|
|
3458
4019
|
|
|
3459
|
-
export type
|
|
4020
|
+
export type APY = {
|
|
4021
|
+
grossAPY: Decimal;
|
|
4022
|
+
netAPY: Decimal;
|
|
4023
|
+
};
|
|
4024
|
+
|
|
4025
|
+
export type VaultAPYs = {
|
|
4026
|
+
theoreticalAPY: APY;
|
|
4027
|
+
actualAPY: APY;
|
|
4028
|
+
};
|
|
4029
|
+
|
|
4030
|
+
export class VaultHoldings {
|
|
3460
4031
|
available: Decimal;
|
|
3461
4032
|
invested: Decimal;
|
|
3462
4033
|
investedInReserves: Map<Address, Decimal>;
|
|
3463
4034
|
pendingFees: Decimal;
|
|
3464
4035
|
totalAUMIncludingFees: Decimal;
|
|
3465
|
-
|
|
4036
|
+
|
|
4037
|
+
constructor(params: {
|
|
4038
|
+
available: Decimal;
|
|
4039
|
+
invested: Decimal;
|
|
4040
|
+
investedInReserves: Map<Address, Decimal>;
|
|
4041
|
+
pendingFees: Decimal;
|
|
4042
|
+
totalAUMIncludingFees: Decimal;
|
|
4043
|
+
}) {
|
|
4044
|
+
this.available = params.available;
|
|
4045
|
+
this.invested = params.invested;
|
|
4046
|
+
this.investedInReserves = params.investedInReserves;
|
|
4047
|
+
this.pendingFees = params.pendingFees;
|
|
4048
|
+
this.totalAUMIncludingFees = params.totalAUMIncludingFees;
|
|
4049
|
+
}
|
|
4050
|
+
|
|
4051
|
+
asJSON() {
|
|
4052
|
+
return {
|
|
4053
|
+
available: this.available.toString(),
|
|
4054
|
+
invested: this.invested.toString(),
|
|
4055
|
+
totalAUMIncludingFees: this.totalAUMIncludingFees.toString(),
|
|
4056
|
+
pendingFees: this.pendingFees.toString(),
|
|
4057
|
+
investedInReserves: pubkeyHashMapToJson(this.investedInReserves),
|
|
4058
|
+
};
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
print() {
|
|
4062
|
+
console.log('Holdings:');
|
|
4063
|
+
console.log(' Available:', this.available.toString());
|
|
4064
|
+
console.log(' Invested:', this.invested.toString());
|
|
4065
|
+
console.log(' Total AUM including fees:', this.totalAUMIncludingFees.toString());
|
|
4066
|
+
console.log(' Pending fees:', this.pendingFees.toString());
|
|
4067
|
+
console.log(' Invested in reserves:', pubkeyHashMapToJson(this.investedInReserves));
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
3466
4070
|
|
|
3467
4071
|
/**
|
|
3468
4072
|
* earnedInterest represents the interest earned from now until the slot provided in the future
|
|
@@ -3518,6 +4122,7 @@ export type VaultOverview = {
|
|
|
3518
4122
|
actualSupplyAPY: APYs;
|
|
3519
4123
|
vaultFarmIncentives: FarmIncentives;
|
|
3520
4124
|
reservesFarmsIncentives: VaultReservesFarmsIncentives;
|
|
4125
|
+
delegatedFarmIncentives: FarmIncentives;
|
|
3521
4126
|
totalBorrowed: Decimal;
|
|
3522
4127
|
totalBorrowedUSD: Decimal;
|
|
3523
4128
|
totalSupplied: Decimal;
|
|
@@ -3545,11 +4150,9 @@ export type VaultCumulativeInterestWithTimestamp = {
|
|
|
3545
4150
|
timestamp: number;
|
|
3546
4151
|
};
|
|
3547
4152
|
|
|
3548
|
-
export
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
console.log(' Invested in reserves:', pubkeyHashMapToJson(holdings.investedInReserves));
|
|
3555
|
-
}
|
|
4153
|
+
export type PendingRewardsForUserInVault = {
|
|
4154
|
+
pendingRewardsInVaultFarm: Map<Address, Decimal>;
|
|
4155
|
+
pendingRewardsInVaultDelegatedFarm: Map<Address, Decimal>;
|
|
4156
|
+
pendingRewardsInVaultReservesFarms: Map<Address, Decimal>;
|
|
4157
|
+
totalPendingRewards: Map<Address, Decimal>;
|
|
4158
|
+
};
|