@kamino-finance/klend-sdk 5.10.32 → 5.10.34
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/action.d.ts +3 -2
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +14 -13
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts +4 -4
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +2 -2
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/types.d.ts +4 -0
- package/dist/classes/types.d.ts.map +1 -1
- package/dist/classes/vault.d.ts +4 -4
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +35 -22
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.js +2 -2
- package/dist/utils/instruction.d.ts.map +1 -1
- package/dist/utils/instruction.js +1 -3
- package/dist/utils/instruction.js.map +1 -1
- package/package.json +2 -2
- package/src/classes/action.ts +23 -22
- package/src/classes/manager.ts +4 -3
- package/src/classes/types.ts +5 -0
- package/src/classes/vault.ts +43 -30
- package/src/client_kamino_manager.ts +2 -2
- package/src/utils/instruction.ts +1 -3
package/src/classes/vault.ts
CHANGED
|
@@ -70,6 +70,7 @@ import bs58 from 'bs58';
|
|
|
70
70
|
import { getAccountOwner, getProgramAccounts } from '../utils/rpc';
|
|
71
71
|
import {
|
|
72
72
|
AcceptVaultOwnershipIxs,
|
|
73
|
+
APYs,
|
|
73
74
|
DepositIxs,
|
|
74
75
|
InitVaultIxs,
|
|
75
76
|
ReserveAllocationOverview,
|
|
@@ -98,7 +99,7 @@ export const kaminoVaultStagingId = new PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuY
|
|
|
98
99
|
const TOKEN_VAULT_SEED = 'token_vault';
|
|
99
100
|
const CTOKEN_VAULT_SEED = 'ctoken_vault';
|
|
100
101
|
const BASE_VAULT_AUTHORITY_SEED = 'authority';
|
|
101
|
-
const
|
|
102
|
+
const SHARES_SEED = 'shares';
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
105
|
* KaminoVaultClient is a class that provides a high-level interface to interact with the Kamino Vault program.
|
|
@@ -191,7 +192,7 @@ export class KaminoVaultClient {
|
|
|
191
192
|
)[0];
|
|
192
193
|
|
|
193
194
|
const sharesMint = PublicKey.findProgramAddressSync(
|
|
194
|
-
[Buffer.from(
|
|
195
|
+
[Buffer.from(SHARES_SEED), vaultState.publicKey.toBytes()],
|
|
195
196
|
this._kaminoVaultProgramId
|
|
196
197
|
)[0];
|
|
197
198
|
|
|
@@ -1005,6 +1006,7 @@ export class KaminoVaultClient {
|
|
|
1005
1006
|
*/
|
|
1006
1007
|
async investAllReservesIxs(payer: PublicKey, vault: KaminoVault): Promise<TransactionInstruction[]> {
|
|
1007
1008
|
const vaultState = await vault.getState(this.getConnection());
|
|
1009
|
+
const minInvestAmount = vaultState.minInvestAmount;
|
|
1008
1010
|
const allReserves = this.getVaultReserves(vaultState);
|
|
1009
1011
|
if (allReserves.length === 0) {
|
|
1010
1012
|
throw new Error('No reserves found for the vault, please select at least one reserve for the vault');
|
|
@@ -1024,6 +1026,7 @@ export class KaminoVaultClient {
|
|
|
1024
1026
|
const curentVaultAllocations = this.getVaultAllocations(vaultState);
|
|
1025
1027
|
|
|
1026
1028
|
const reservesToDisinvestFrom: PublicKey[] = [];
|
|
1029
|
+
const reservesToInvestInto: PublicKey[] = [];
|
|
1027
1030
|
|
|
1028
1031
|
for (let index = 0; index < allReserves.length; index++) {
|
|
1029
1032
|
const reservePubkey = allReserves[index];
|
|
@@ -1037,8 +1040,15 @@ export class KaminoVaultClient {
|
|
|
1037
1040
|
vaultState.tokenMintDecimals.toNumber()
|
|
1038
1041
|
);
|
|
1039
1042
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1043
|
+
const diffInReserveTokens = computedAllocation.sub(reserveAllocationLiquidityAmount);
|
|
1044
|
+
const diffInReserveLamports = collToLamportsDecimal(diffInReserveTokens, vaultState.tokenMintDecimals.toNumber());
|
|
1045
|
+
// if the diff for the reserve is smaller than the min invest amount, we do not need to invest or disinvest
|
|
1046
|
+
if (diffInReserveLamports.abs().gte(new Decimal(minInvestAmount.toString()))) {
|
|
1047
|
+
if (computedAllocation.lt(reserveAllocationLiquidityAmount)) {
|
|
1048
|
+
reservesToDisinvestFrom.push(reservePubkey);
|
|
1049
|
+
} else {
|
|
1050
|
+
reservesToInvestInto.push(reservePubkey);
|
|
1051
|
+
}
|
|
1042
1052
|
}
|
|
1043
1053
|
}
|
|
1044
1054
|
|
|
@@ -1062,24 +1072,22 @@ export class KaminoVaultClient {
|
|
|
1062
1072
|
investIxnsPromises.push(investIxsPromise);
|
|
1063
1073
|
}
|
|
1064
1074
|
|
|
1065
|
-
for (const reserve of
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
throw new Error(`Reserve ${reserve.toBase58()} not found`);
|
|
1070
|
-
}
|
|
1071
|
-
const investIxsPromise = this.investSingleReserveIxs(
|
|
1072
|
-
payer,
|
|
1073
|
-
vault,
|
|
1074
|
-
{
|
|
1075
|
-
address: reserve,
|
|
1076
|
-
state: reserveState!.state,
|
|
1077
|
-
},
|
|
1078
|
-
allReservesStateMap,
|
|
1079
|
-
false
|
|
1080
|
-
);
|
|
1081
|
-
investIxnsPromises.push(investIxsPromise);
|
|
1075
|
+
for (const reserve of reservesToInvestInto) {
|
|
1076
|
+
const reserveState = allReservesStateMap.get(reserve);
|
|
1077
|
+
if (reserveState === null) {
|
|
1078
|
+
throw new Error(`Reserve ${reserve.toBase58()} not found`);
|
|
1082
1079
|
}
|
|
1080
|
+
const investIxsPromise = this.investSingleReserveIxs(
|
|
1081
|
+
payer,
|
|
1082
|
+
vault,
|
|
1083
|
+
{
|
|
1084
|
+
address: reserve,
|
|
1085
|
+
state: reserveState!.state,
|
|
1086
|
+
},
|
|
1087
|
+
allReservesStateMap,
|
|
1088
|
+
false
|
|
1089
|
+
);
|
|
1090
|
+
investIxnsPromises.push(investIxsPromise);
|
|
1083
1091
|
}
|
|
1084
1092
|
|
|
1085
1093
|
let investIxns: TransactionInstruction[] = [];
|
|
@@ -1500,7 +1508,7 @@ export class KaminoVaultClient {
|
|
|
1500
1508
|
const allocation = reservesAllocations.get(reserve);
|
|
1501
1509
|
return allocation?.targetWeight.isZero();
|
|
1502
1510
|
});
|
|
1503
|
-
if (
|
|
1511
|
+
if (allReservesPubkeys.length === 0 || allReservesHaveWeight0) {
|
|
1504
1512
|
const computedHoldings = new PubkeyHashMap<PublicKey, Decimal>();
|
|
1505
1513
|
allReservesPubkeys.forEach((reserve) => {
|
|
1506
1514
|
computedHoldings.set(reserve, new Decimal(0));
|
|
@@ -1528,7 +1536,6 @@ export class KaminoVaultClient {
|
|
|
1528
1536
|
const reserveWithWeight = initialVaultAllocations.get(reserve);
|
|
1529
1537
|
const targetAllocation = reserveWithWeight!.targetWeight.mul(totalLeftover).div(currentAllocationSum);
|
|
1530
1538
|
const reserveCap = reserveWithWeight!.tokenAllocationCap;
|
|
1531
|
-
// todo: check if both target and reserveCap
|
|
1532
1539
|
const amountToInvest = Decimal.min(targetAllocation, reserveCap, totalLeftToInvest);
|
|
1533
1540
|
totalLeftToInvest = totalLeftToInvest.sub(amountToInvest);
|
|
1534
1541
|
if (amountToInvest.eq(reserveCap)) {
|
|
@@ -2224,7 +2231,7 @@ export class KaminoVaultClient {
|
|
|
2224
2231
|
// 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
|
|
2225
2232
|
const [
|
|
2226
2233
|
vaultHoldingsWithUSDValue,
|
|
2227
|
-
|
|
2234
|
+
vaultTheoreticalAPYs,
|
|
2228
2235
|
totalInvestedAndBorrowed,
|
|
2229
2236
|
vaultCollaterals,
|
|
2230
2237
|
reservesOverview,
|
|
@@ -2240,7 +2247,7 @@ export class KaminoVaultClient {
|
|
|
2240
2247
|
holdingsUSD: vaultHoldingsWithUSDValue,
|
|
2241
2248
|
reservesOverview: reservesOverview,
|
|
2242
2249
|
vaultCollaterals: vaultCollaterals,
|
|
2243
|
-
theoreticalSupplyAPY:
|
|
2250
|
+
theoreticalSupplyAPY: vaultTheoreticalAPYs,
|
|
2244
2251
|
totalBorrowed: totalInvestedAndBorrowed.totalBorrowed,
|
|
2245
2252
|
utilizationRatio: totalInvestedAndBorrowed.utilizationRatio,
|
|
2246
2253
|
totalSupplied: totalInvestedAndBorrowed.totalInvested,
|
|
@@ -2351,13 +2358,13 @@ export class KaminoVaultClient {
|
|
|
2351
2358
|
* @param vault - the kamino vault to get APY for
|
|
2352
2359
|
* @param slot - current slot
|
|
2353
2360
|
* @param [vaultReservesMap] - 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
|
|
2354
|
-
* @returns APY for the vault
|
|
2361
|
+
* @returns a struct containing estimated gross APY and net APY (gross - vault fees) for the vault
|
|
2355
2362
|
*/
|
|
2356
2363
|
async getVaultTheoreticalAPY(
|
|
2357
2364
|
vault: VaultState,
|
|
2358
2365
|
slot: number,
|
|
2359
2366
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
2360
|
-
): Promise<
|
|
2367
|
+
): Promise<APYs> {
|
|
2361
2368
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vault);
|
|
2362
2369
|
|
|
2363
2370
|
let totalWeights = new Decimal(0);
|
|
@@ -2379,14 +2386,20 @@ export class KaminoVaultClient {
|
|
|
2379
2386
|
totalWeights = totalWeights.add(weight);
|
|
2380
2387
|
});
|
|
2381
2388
|
if (totalWeights.isZero()) {
|
|
2382
|
-
return
|
|
2389
|
+
return {
|
|
2390
|
+
grossAPY: new Decimal(0),
|
|
2391
|
+
netAPY: new Decimal(0),
|
|
2392
|
+
};
|
|
2383
2393
|
}
|
|
2384
2394
|
|
|
2385
2395
|
const grossAPY = totalAPY.div(totalWeights);
|
|
2386
2396
|
const netAPY = grossAPY
|
|
2387
2397
|
.mul(new Decimal(1).sub(new Decimal(vault.performanceFeeBps.toString()).div(FullBPSDecimal)))
|
|
2388
2398
|
.mul(new Decimal(1).sub(new Decimal(vault.managementFeeBps.toString()).div(FullBPSDecimal)));
|
|
2389
|
-
return
|
|
2399
|
+
return {
|
|
2400
|
+
grossAPY,
|
|
2401
|
+
netAPY,
|
|
2402
|
+
};
|
|
2390
2403
|
}
|
|
2391
2404
|
|
|
2392
2405
|
/**
|
|
@@ -2655,7 +2668,7 @@ export type VaultOverview = {
|
|
|
2655
2668
|
holdingsUSD: VaultHoldingsWithUSDValue;
|
|
2656
2669
|
reservesOverview: PubkeyHashMap<PublicKey, ReserveOverview>;
|
|
2657
2670
|
vaultCollaterals: PubkeyHashMap<PublicKey, MarketOverview>;
|
|
2658
|
-
theoreticalSupplyAPY:
|
|
2671
|
+
theoreticalSupplyAPY: APYs;
|
|
2659
2672
|
totalBorrowed: Decimal;
|
|
2660
2673
|
totalSupplied: Decimal;
|
|
2661
2674
|
utilizationRatio: Decimal;
|
|
@@ -260,7 +260,7 @@ async function main() {
|
|
|
260
260
|
2500,
|
|
261
261
|
[vaultKp]
|
|
262
262
|
);
|
|
263
|
-
await sleep(
|
|
263
|
+
await sleep(2000);
|
|
264
264
|
const _populateLUTSig = await processTxn(env.client, env.payer, instructions.populateLUTIxs, mode, 2500, []);
|
|
265
265
|
|
|
266
266
|
mode === 'execute' && console.log('Vault created:', vaultKp.publicKey.toBase58());
|
|
@@ -426,7 +426,7 @@ async function main() {
|
|
|
426
426
|
// if we need to create the LUT we have to do that in a separate tx and wait a little bit after
|
|
427
427
|
if (syncLUTIxs.setupLUTIfNeededIxs.length > 0) {
|
|
428
428
|
const setupLUTSig = await processTxn(env.client, env.payer, syncLUTIxs.setupLUTIfNeededIxs, mode, 2500, []);
|
|
429
|
-
await sleep(
|
|
429
|
+
await sleep(2000);
|
|
430
430
|
mode === 'execute' && console.log('LUT created and set to the vault:', setupLUTSig);
|
|
431
431
|
}
|
|
432
432
|
// if there are accounts to be added to the LUT we have to do that in a separate tx
|
package/src/utils/instruction.ts
CHANGED
|
@@ -38,7 +38,7 @@ export async function buildAndSendTxnWithLogs(
|
|
|
38
38
|
});
|
|
39
39
|
console.log('Transaction Hash:', withDescription, sig);
|
|
40
40
|
if (withLogsIfSuccess) {
|
|
41
|
-
await sleep(
|
|
41
|
+
await sleep(1000);
|
|
42
42
|
const res = await c.getTransaction(sig, {
|
|
43
43
|
commitment: 'confirmed',
|
|
44
44
|
maxSupportedTransactionVersion: 6,
|
|
@@ -49,7 +49,6 @@ export async function buildAndSendTxnWithLogs(
|
|
|
49
49
|
} catch (e: any) {
|
|
50
50
|
console.log(e);
|
|
51
51
|
process.stdout.write(e.logs.toString());
|
|
52
|
-
await sleep(5000);
|
|
53
52
|
const sig = e.toString().split(' failed ')[0].split('Transaction ')[1];
|
|
54
53
|
const res: VersionedTransactionResponse | null = await c.getTransaction(sig, {
|
|
55
54
|
commitment: 'confirmed',
|
|
@@ -115,7 +114,6 @@ export async function simulateTxn(c: Connection, tx: Transaction, owner: Keypair
|
|
|
115
114
|
} catch (e: any) {
|
|
116
115
|
console.log(e);
|
|
117
116
|
process.stdout.write(e.logs.toString());
|
|
118
|
-
await sleep(5000);
|
|
119
117
|
const sig = e.toString().split(' failed ')[0].split('Transaction ')[1];
|
|
120
118
|
const res: TransactionResponse | null = await c.getTransaction(sig, {
|
|
121
119
|
commitment: 'confirmed',
|