@kamino-finance/klend-sdk 5.10.7 → 5.10.8
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 +20 -18
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +27 -20
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/types_utils.d.ts +11 -0
- package/dist/classes/types_utils.d.ts.map +1 -0
- package/dist/classes/types_utils.js +21 -0
- package/dist/classes/types_utils.js.map +1 -0
- package/dist/classes/utils.d.ts +7 -0
- package/dist/classes/utils.d.ts.map +1 -1
- package/dist/classes/utils.js +21 -0
- package/dist/classes/utils.js.map +1 -1
- package/dist/classes/vault.d.ts +23 -14
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +65 -33
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +25 -2
- package/dist/client_kamino_manager.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +40 -23
- package/src/classes/types_utils.ts +19 -0
- package/src/classes/utils.ts +22 -1
- package/src/classes/vault.ts +93 -41
- package/src/client_kamino_manager.ts +43 -4
package/src/classes/manager.ts
CHANGED
|
@@ -66,7 +66,7 @@ import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
|
66
66
|
import { Data } from '@kamino-finance/kliquidity-sdk';
|
|
67
67
|
import bs58 from 'bs58';
|
|
68
68
|
import { getProgramAccounts } from '../utils/rpc';
|
|
69
|
-
import { VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
|
|
69
|
+
import { VaultConfigField, VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
|
|
70
70
|
import {
|
|
71
71
|
AcceptVaultOwnershipIxs,
|
|
72
72
|
DepositIxs,
|
|
@@ -369,9 +369,14 @@ export class KaminoManager {
|
|
|
369
369
|
*/
|
|
370
370
|
async updateVaultConfigIxs(
|
|
371
371
|
vault: KaminoVault,
|
|
372
|
-
mode: VaultConfigFieldKind,
|
|
372
|
+
mode: VaultConfigFieldKind | string,
|
|
373
373
|
value: string
|
|
374
374
|
): Promise<UpdateVaultConfigIxs> {
|
|
375
|
+
if (typeof mode === 'string') {
|
|
376
|
+
const field = VaultConfigField.fromDecoded({ [mode]: '' });
|
|
377
|
+
return this._vaultClient.updateVaultConfigIxs(vault, field, value);
|
|
378
|
+
}
|
|
379
|
+
|
|
375
380
|
return this._vaultClient.updateVaultConfigIxs(vault, mode, value);
|
|
376
381
|
}
|
|
377
382
|
|
|
@@ -465,21 +470,26 @@ export class KaminoManager {
|
|
|
465
470
|
/**
|
|
466
471
|
* This method calculates the token per share value. This will always change based on interest earned from the vault, but calculating it requires a bunch of rpc requests. Caching this for a short duration would be optimal
|
|
467
472
|
* @param vault - vault to calculate tokensPerShare for
|
|
468
|
-
* @param slot -
|
|
473
|
+
* @param [slot] - the slot at which we retrieve the tokens per share. Optional. If not provided, the function will fetch the current slot
|
|
474
|
+
* @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
|
|
469
475
|
* @returns - token per share value
|
|
470
476
|
*/
|
|
471
|
-
async getTokensPerShareSingleVault(
|
|
472
|
-
|
|
477
|
+
async getTokensPerShareSingleVault(
|
|
478
|
+
vault: KaminoVault,
|
|
479
|
+
slot?: number,
|
|
480
|
+
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
481
|
+
): Promise<Decimal> {
|
|
482
|
+
return this._vaultClient.getTokensPerShareSingleVault(vault, slot, vaultReservesMap);
|
|
473
483
|
}
|
|
474
484
|
|
|
475
485
|
/**
|
|
476
486
|
* This method calculates the price of one vault share(kToken)
|
|
477
487
|
* @param vault - vault to calculate sharePrice for
|
|
478
|
-
* @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
|
|
479
488
|
* @param tokenPrice - the price of the vault token (e.g. SOL) in USD
|
|
489
|
+
* @param [slot] - the slot at which we retrieve the tokens per share. Optional. If not provided, the function will fetch the current slot
|
|
480
490
|
* @returns - share value in USD
|
|
481
491
|
*/
|
|
482
|
-
async getSharePriceInUSD(vault: KaminoVault,
|
|
492
|
+
async getSharePriceInUSD(vault: KaminoVault, tokenPrice: Decimal, slot?: number): Promise<Decimal> {
|
|
483
493
|
const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
|
|
484
494
|
return tokensPerShare.mul(tokenPrice);
|
|
485
495
|
}
|
|
@@ -638,13 +648,13 @@ export class KaminoManager {
|
|
|
638
648
|
/**
|
|
639
649
|
* 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
|
|
640
650
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
641
|
-
* @param slot - current slot
|
|
642
|
-
* @param vaultReserves -
|
|
651
|
+
* @param [slot] - the slot for which to calculate the holdings. Optional. If not provided the function will fetch the current slot
|
|
652
|
+
* @param [vaultReserves] - 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
|
|
643
653
|
* @returns an VaultHoldings object
|
|
644
654
|
*/
|
|
645
655
|
async getVaultHoldings(
|
|
646
656
|
vault: VaultState,
|
|
647
|
-
slot
|
|
657
|
+
slot?: number,
|
|
648
658
|
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
649
659
|
): Promise<VaultHoldings> {
|
|
650
660
|
return this._vaultClient.getVaultHoldings(vault, slot, vaultReserves);
|
|
@@ -653,37 +663,37 @@ export class KaminoManager {
|
|
|
653
663
|
/**
|
|
654
664
|
* This will return an VaultHoldingsWithUSDValue object which contains an holdings field representing the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve and additional fields for the total USD value of the available and invested amounts
|
|
655
665
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
656
|
-
* @param slot - current slot
|
|
657
|
-
* @param vaultReserves - 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
|
|
658
666
|
* @param price - the price of the token in the vault (e.g. USDC)
|
|
667
|
+
* @param [slot] - the slot for which to calculate the holdings. Optional. If not provided the function will fetch the current slot
|
|
668
|
+
* @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
|
|
659
669
|
* @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
|
|
660
670
|
*/
|
|
661
671
|
async getVaultHoldingsWithPrice(
|
|
662
672
|
vault: VaultState,
|
|
663
|
-
slot: number,
|
|
664
673
|
price: Decimal,
|
|
674
|
+
slot?: number,
|
|
665
675
|
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
666
676
|
): Promise<VaultHoldingsWithUSDValue> {
|
|
667
|
-
return this._vaultClient.getVaultHoldingsWithPrice(vault,
|
|
677
|
+
return this._vaultClient.getVaultHoldingsWithPrice(vault, price, slot, vaultReserves);
|
|
668
678
|
}
|
|
669
679
|
|
|
670
680
|
/**
|
|
671
681
|
* This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, utilization ratio and total borrowed amount
|
|
672
682
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
673
|
-
* @param slot - current slot
|
|
674
683
|
* @param price - the price of the token in the vault (e.g. USDC)
|
|
675
|
-
* @param
|
|
676
|
-
* @param
|
|
677
|
-
* @
|
|
684
|
+
* @param [slot] - the slot for which to retrieve the vault overview for. Optional. If not provided the function will fetch the current slot
|
|
685
|
+
* @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
|
|
686
|
+
* @param [kaminoMarkets] - a list of all kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
|
|
687
|
+
* @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD
|
|
678
688
|
*/
|
|
679
689
|
async getVaultOverview(
|
|
680
690
|
vault: VaultState,
|
|
681
|
-
slot: number,
|
|
682
691
|
price: Decimal,
|
|
692
|
+
slot?: number,
|
|
683
693
|
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
684
694
|
kaminoMarkets?: KaminoMarket[]
|
|
685
695
|
): Promise<VaultOverview> {
|
|
686
|
-
return this._vaultClient.getVaultOverview(vault,
|
|
696
|
+
return this._vaultClient.getVaultOverview(vault, price, slot, vaultReserves, kaminoMarkets);
|
|
687
697
|
}
|
|
688
698
|
|
|
689
699
|
/**
|
|
@@ -743,16 +753,23 @@ export class KaminoManager {
|
|
|
743
753
|
/**
|
|
744
754
|
* Simulate the current holdings of the vault and the earned interest
|
|
745
755
|
* @param vaultState the kamino vault state to get simulated holdings and earnings for
|
|
746
|
-
* @param
|
|
756
|
+
* @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
|
|
747
757
|
* @param [currentSlot] - the current slot. Optional. If not provided it will fetch the current slot
|
|
758
|
+
* @param [previousTotalAUM] - the previous AUM of the vault to compute the earned interest relative to this value. Optional. If not provided the function will estimate the total AUM at the slot of the last state update on chain
|
|
748
759
|
* @returns a struct of simulated vault holdings and earned interest
|
|
749
760
|
*/
|
|
750
761
|
async calculateSimulatedHoldingsWithInterest(
|
|
751
762
|
vaultState: VaultState,
|
|
752
763
|
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
753
|
-
currentSlot?: number
|
|
764
|
+
currentSlot?: number,
|
|
765
|
+
previousTotalAUM?: Decimal
|
|
754
766
|
): Promise<SimulatedVaultHoldingsWithEarnedInterest> {
|
|
755
|
-
return this._vaultClient.calculateSimulatedHoldingsWithInterest(
|
|
767
|
+
return this._vaultClient.calculateSimulatedHoldingsWithInterest(
|
|
768
|
+
vaultState,
|
|
769
|
+
vaultReserves,
|
|
770
|
+
currentSlot,
|
|
771
|
+
previousTotalAUM
|
|
772
|
+
);
|
|
756
773
|
}
|
|
757
774
|
|
|
758
775
|
/**
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { pubkeyHashMapToJson } from './utils';
|
|
2
|
+
import { VaultHoldings } from './vault';
|
|
3
|
+
|
|
4
|
+
export function holdingsToJson(holdings: VaultHoldings) {
|
|
5
|
+
return {
|
|
6
|
+
available: holdings.available.toString(),
|
|
7
|
+
invested: holdings.invested.toString(),
|
|
8
|
+
total: holdings.total.toString(),
|
|
9
|
+
investedInReserves: pubkeyHashMapToJson(holdings.investedInReserves),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function printHoldings(holdings: VaultHoldings) {
|
|
14
|
+
console.log('Holdings:');
|
|
15
|
+
console.log(' Available:', holdings.available.toString());
|
|
16
|
+
console.log(' Invested:', holdings.invested.toString());
|
|
17
|
+
console.log(' Total:', holdings.total.toString());
|
|
18
|
+
console.log(' Invested in reserves:', pubkeyHashMapToJson(holdings.investedInReserves));
|
|
19
|
+
}
|
package/src/classes/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SLOTS_PER_SECOND, SLOTS_PER_YEAR } from '../utils';
|
|
1
|
+
import { PubkeyHashMap, SLOTS_PER_SECOND, SLOTS_PER_YEAR } from '../utils';
|
|
2
2
|
import Decimal from 'decimal.js';
|
|
3
3
|
import { AccountInfo, PublicKey } from '@solana/web3.js';
|
|
4
4
|
import { SOL_MINTS } from '../lib';
|
|
@@ -250,3 +250,24 @@ export function truncateDecimals(num: Decimal.Value, maxDecimals: number): Decim
|
|
|
250
250
|
const factor = new Decimal(10).pow(maxDecimals);
|
|
251
251
|
return new Decimal(num).times(factor).floor().dividedBy(factor);
|
|
252
252
|
}
|
|
253
|
+
|
|
254
|
+
/**Convert an u8 array to a string */
|
|
255
|
+
export function decodeVaultName(token: number[]): string {
|
|
256
|
+
const maxArray = new Uint8Array(token);
|
|
257
|
+
let s: string = new TextDecoder().decode(maxArray);
|
|
258
|
+
// Remove trailing zeros and spaces
|
|
259
|
+
s = s.replace(/[\0 ]+$/, '');
|
|
260
|
+
return s;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function pubkeyHashMapToJson(map: PubkeyHashMap<PublicKey, any>): { [key: string]: string } {
|
|
264
|
+
const obj: { [key: string]: any } = {};
|
|
265
|
+
map.forEach((value, key) => {
|
|
266
|
+
obj[key.toBase58()] = value.toString();
|
|
267
|
+
});
|
|
268
|
+
return obj;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function printPubkeyHashMap<V>(map: PubkeyHashMap<PublicKey, V>) {
|
|
272
|
+
console.log(pubkeyHashMapToJson(map));
|
|
273
|
+
}
|
package/src/classes/vault.ts
CHANGED
|
@@ -53,7 +53,13 @@ import {
|
|
|
53
53
|
import { VaultConfigField, VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
|
|
54
54
|
import { VaultState } from '../idl_codegen_kamino_vault/accounts';
|
|
55
55
|
import Decimal from 'decimal.js';
|
|
56
|
-
import {
|
|
56
|
+
import {
|
|
57
|
+
bpsToPct,
|
|
58
|
+
decodeVaultName,
|
|
59
|
+
getTokenBalanceFromAccountInfoLamports,
|
|
60
|
+
numberToLamportsDecimal,
|
|
61
|
+
parseTokenSymbol,
|
|
62
|
+
} from './utils';
|
|
57
63
|
import { deposit } from '../idl_codegen_kamino_vault/instructions';
|
|
58
64
|
import { withdraw } from '../idl_codegen_kamino_vault/instructions';
|
|
59
65
|
import { PROGRAM_ID } from '../idl_codegen/programId';
|
|
@@ -83,6 +89,7 @@ import {
|
|
|
83
89
|
getSharesInFarmUserPosition,
|
|
84
90
|
getUserSharesInFarm,
|
|
85
91
|
} from './farm_utils';
|
|
92
|
+
import { printHoldings } from './types_utils';
|
|
86
93
|
|
|
87
94
|
export const kaminoVaultId = new PublicKey('kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr');
|
|
88
95
|
export const kaminoVaultStagingId = new PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuYMFMTsE77FiRsL2');
|
|
@@ -125,6 +132,36 @@ export class KaminoVaultClient {
|
|
|
125
132
|
return;
|
|
126
133
|
}
|
|
127
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Prints a vault in a human readable form
|
|
137
|
+
* @param vaultPubkey - the address of the vault
|
|
138
|
+
* @param [vaultState] - optional parameter to pass the vault state directly; this will save a network call
|
|
139
|
+
* @returns - void; prints the vault to the console
|
|
140
|
+
*/
|
|
141
|
+
async printVault(vaultPubkey: PublicKey, vaultState?: VaultState) {
|
|
142
|
+
const vault = vaultState ? vaultState : await VaultState.fetch(this.getConnection(), vaultPubkey);
|
|
143
|
+
|
|
144
|
+
if (!vault) {
|
|
145
|
+
console.log(`Vault ${vaultPubkey.toString()} not found`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const kaminoVault = new KaminoVault(vaultPubkey, vault, this._kaminoVaultProgramId);
|
|
150
|
+
const vaultName = this.decodeVaultName(vault.name);
|
|
151
|
+
const slot = await this.getConnection().getSlot('confirmed');
|
|
152
|
+
const tokensPerShare = await this.getTokensPerShareSingleVault(kaminoVault, slot);
|
|
153
|
+
const holdings = await this.getVaultHoldings(vault);
|
|
154
|
+
|
|
155
|
+
const sharesIssued = new Decimal(vault.sharesIssued.toString()!).div(
|
|
156
|
+
new Decimal(vault.sharesMintDecimals.toString())
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
console.log('Name: ', vaultName);
|
|
160
|
+
console.log('Shares issued: ', sharesIssued);
|
|
161
|
+
printHoldings(holdings);
|
|
162
|
+
console.log('Tokens per share: ', tokensPerShare);
|
|
163
|
+
}
|
|
164
|
+
|
|
128
165
|
/**
|
|
129
166
|
* This method will create a vault with a given config. The config can be changed later on, but it is recommended to set it up correctly from the start
|
|
130
167
|
* @param vaultConfig - the config object used to create a vault
|
|
@@ -1058,11 +1095,7 @@ export class KaminoVaultClient {
|
|
|
1058
1095
|
|
|
1059
1096
|
/**Convert an u8 array to a string */
|
|
1060
1097
|
decodeVaultName(token: number[]): string {
|
|
1061
|
-
|
|
1062
|
-
let s: string = new TextDecoder().decode(maxArray);
|
|
1063
|
-
// Remove trailing zeros and spaces
|
|
1064
|
-
s = s.replace(/[\0 ]+$/, '');
|
|
1065
|
-
return s;
|
|
1098
|
+
return decodeVaultName(token);
|
|
1066
1099
|
}
|
|
1067
1100
|
|
|
1068
1101
|
private withdrawIxn(
|
|
@@ -1491,15 +1524,15 @@ export class KaminoVaultClient {
|
|
|
1491
1524
|
}
|
|
1492
1525
|
|
|
1493
1526
|
/**
|
|
1494
|
-
* This method calculates the token per
|
|
1527
|
+
* This method calculates the token per share value. This will always change based on interest earned from the vault, but calculating it requires a bunch of rpc requests. Caching this for a short duration would be optimal
|
|
1495
1528
|
* @param vault - vault to calculate tokensPerShare for
|
|
1496
|
-
* @param slot -
|
|
1529
|
+
* @param [slot] - the slot at which we retrieve the tokens per share. Optional. If not provided, the function will fetch the current slot
|
|
1497
1530
|
* @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
|
|
1498
1531
|
* @returns - token per share value
|
|
1499
1532
|
*/
|
|
1500
1533
|
async getTokensPerShareSingleVault(
|
|
1501
1534
|
vault: KaminoVault,
|
|
1502
|
-
slot
|
|
1535
|
+
slot?: number,
|
|
1503
1536
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
1504
1537
|
): Promise<Decimal> {
|
|
1505
1538
|
const vaultState = await vault.getState(this.getConnection());
|
|
@@ -1514,11 +1547,7 @@ export class KaminoVaultClient {
|
|
|
1514
1547
|
vaultState.sharesMintDecimals.toString()
|
|
1515
1548
|
);
|
|
1516
1549
|
|
|
1517
|
-
const holdings = await this.getVaultHoldings(
|
|
1518
|
-
vaultState,
|
|
1519
|
-
await this.getConnection().getSlot('confirmed'),
|
|
1520
|
-
vaultReservesState
|
|
1521
|
-
);
|
|
1550
|
+
const holdings = await this.getVaultHoldings(vaultState, slot, vaultReservesState);
|
|
1522
1551
|
|
|
1523
1552
|
return holdings.total.div(sharesDecimal);
|
|
1524
1553
|
}
|
|
@@ -1759,7 +1788,7 @@ export class KaminoVaultClient {
|
|
|
1759
1788
|
/**
|
|
1760
1789
|
* This will retrieve all the tokens that can be used as collateral by the users who borrow the token in the vault alongside details about the min and max loan to value ratio
|
|
1761
1790
|
* @param vaultState - the vault state to load reserves for
|
|
1762
|
-
* @param slot - current slot
|
|
1791
|
+
* @param [slot] - the slot for which to retrieve the vault collaterals for. Optional. If not provided the function will fetch the current slot
|
|
1763
1792
|
* @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
|
|
1764
1793
|
* @param [kaminoMarkets] - a list of all the kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
|
|
1765
1794
|
* @returns a hashmap from each reserve pubkey to the market overview of the collaterals that can be used and the min and max loan to value ratio in that market
|
|
@@ -1831,13 +1860,13 @@ export class KaminoVaultClient {
|
|
|
1831
1860
|
/**
|
|
1832
1861
|
* 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
|
|
1833
1862
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
1834
|
-
* @param slot - current slot
|
|
1835
|
-
* @param vaultReserves - 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
|
|
1863
|
+
* @param [slot] - the slot for which to calculate the holdings. Optional. If not provided the function will fetch the current slot
|
|
1864
|
+
* @param [vaultReserves] - 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
|
|
1836
1865
|
* @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
|
|
1837
1866
|
*/
|
|
1838
1867
|
async getVaultHoldings(
|
|
1839
1868
|
vault: VaultState,
|
|
1840
|
-
slot
|
|
1869
|
+
slot?: number,
|
|
1841
1870
|
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
1842
1871
|
): Promise<VaultHoldings> {
|
|
1843
1872
|
const vaultHoldings: VaultHoldings = {
|
|
@@ -1860,7 +1889,12 @@ export class KaminoVaultClient {
|
|
|
1860
1889
|
throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
|
|
1861
1890
|
}
|
|
1862
1891
|
|
|
1863
|
-
|
|
1892
|
+
let reserveCollExchangeRate: Decimal;
|
|
1893
|
+
if (slot) {
|
|
1894
|
+
reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(slot, 0);
|
|
1895
|
+
} else {
|
|
1896
|
+
reserveCollExchangeRate = reserve.getCollateralExchangeRate();
|
|
1897
|
+
}
|
|
1864
1898
|
const reserveAllocationLiquidityAmount = new Decimal(allocationStrategy.ctokenAllocation.toString()).div(
|
|
1865
1899
|
reserveCollExchangeRate
|
|
1866
1900
|
);
|
|
@@ -1883,17 +1917,18 @@ export class KaminoVaultClient {
|
|
|
1883
1917
|
}
|
|
1884
1918
|
|
|
1885
1919
|
/**
|
|
1886
|
-
* This will return an
|
|
1920
|
+
* This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, utilization ratio and total borrowed amount
|
|
1887
1921
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
1888
|
-
* @param slot - current slot
|
|
1889
1922
|
* @param price - the price of the token in the vault (e.g. USDC)
|
|
1923
|
+
* @param [slot] - the slot for which to retrieve the vault overview for. Optional. If not provided the function will fetch the current slot
|
|
1890
1924
|
* @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
|
|
1891
|
-
* @
|
|
1925
|
+
* @param [kaminoMarkets] - a list of all kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
|
|
1926
|
+
* @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD
|
|
1892
1927
|
*/
|
|
1893
1928
|
async getVaultHoldingsWithPrice(
|
|
1894
1929
|
vault: VaultState,
|
|
1895
|
-
slot: number,
|
|
1896
1930
|
price: Decimal,
|
|
1931
|
+
slot?: number,
|
|
1897
1932
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
1898
1933
|
): Promise<VaultHoldingsWithUSDValue> {
|
|
1899
1934
|
const holdings = await this.getVaultHoldings(vault, slot, vaultReservesMap);
|
|
@@ -1914,16 +1949,16 @@ export class KaminoVaultClient {
|
|
|
1914
1949
|
/**
|
|
1915
1950
|
* This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, utilization ratio and total borrowed amount
|
|
1916
1951
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
1917
|
-
* @param slot - current slot
|
|
1918
1952
|
* @param price - the price of the token in the vault (e.g. USDC)
|
|
1953
|
+
* @param [slot] - the slot for which to retrieve the vault overview for. Optional. If not provided the function will fetch the current slot
|
|
1919
1954
|
* @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
|
|
1920
1955
|
* @param [kaminoMarkets] - a list of all kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
|
|
1921
1956
|
* @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD
|
|
1922
1957
|
*/
|
|
1923
1958
|
async getVaultOverview(
|
|
1924
1959
|
vault: VaultState,
|
|
1925
|
-
slot: number,
|
|
1926
1960
|
price: Decimal,
|
|
1961
|
+
slot?: number,
|
|
1927
1962
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
1928
1963
|
kaminoMarkets?: KaminoMarket[]
|
|
1929
1964
|
): Promise<VaultOverview> {
|
|
@@ -1931,14 +1966,26 @@ export class KaminoVaultClient {
|
|
|
1931
1966
|
|
|
1932
1967
|
const vaultHoldingsWithUSDValuePromise = await this.getVaultHoldingsWithPrice(
|
|
1933
1968
|
vault,
|
|
1934
|
-
slot,
|
|
1935
1969
|
price,
|
|
1970
|
+
slot,
|
|
1971
|
+
vaultReservesState
|
|
1972
|
+
);
|
|
1973
|
+
|
|
1974
|
+
const currentSlot = slot ? slot : await this.getConnection().getSlot();
|
|
1975
|
+
|
|
1976
|
+
const vaultTheoreticalAPYPromise = await this.getVaultTheoreticalAPY(vault, currentSlot, vaultReservesState);
|
|
1977
|
+
const totalInvestedAndBorrowedPromise = await this.getTotalBorrowedAndInvested(
|
|
1978
|
+
vault,
|
|
1979
|
+
currentSlot,
|
|
1936
1980
|
vaultReservesState
|
|
1937
1981
|
);
|
|
1938
|
-
const
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1982
|
+
const vaultCollateralsPromise = await this.getVaultCollaterals(
|
|
1983
|
+
vault,
|
|
1984
|
+
currentSlot,
|
|
1985
|
+
vaultReservesState,
|
|
1986
|
+
kaminoMarkets
|
|
1987
|
+
);
|
|
1988
|
+
const reservesOverviewPromise = await this.getVaultReservesDetails(vault, currentSlot, vaultReservesState);
|
|
1942
1989
|
|
|
1943
1990
|
// 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
|
|
1944
1991
|
const [
|
|
@@ -2115,26 +2162,31 @@ export class KaminoVaultClient {
|
|
|
2115
2162
|
* @param vaultState the kamino vault state to get simulated holdings and earnings for
|
|
2116
2163
|
* @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
|
|
2117
2164
|
* @param [currentSlot] - the current slot. Optional. If not provided it will fetch the current slot
|
|
2165
|
+
* @param [previousTotalAUM] - the previous AUM of the vault to compute the earned interest relative to this value. Optional. If not provided the function will estimate the total AUM at the slot of the last state update on chain
|
|
2118
2166
|
* @returns a struct of simulated vault holdings and earned interest
|
|
2119
2167
|
*/
|
|
2120
2168
|
async calculateSimulatedHoldingsWithInterest(
|
|
2121
2169
|
vaultState: VaultState,
|
|
2122
2170
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
2123
|
-
currentSlot?: number
|
|
2171
|
+
currentSlot?: number,
|
|
2172
|
+
previousTotalAUM?: Decimal
|
|
2124
2173
|
): Promise<SimulatedVaultHoldingsWithEarnedInterest> {
|
|
2125
|
-
|
|
2126
|
-
const lastUpdateSlot = latestUpdateTs / this.recentSlotDurationMs;
|
|
2174
|
+
let prevAUM: Decimal;
|
|
2127
2175
|
|
|
2128
|
-
|
|
2176
|
+
if (previousTotalAUM) {
|
|
2177
|
+
prevAUM = previousTotalAUM;
|
|
2178
|
+
} else {
|
|
2179
|
+
const latestUpdateTs = vaultState.lastFeeChargeTimestamp.toNumber();
|
|
2180
|
+
const lastUpdateSlot = latestUpdateTs / this.recentSlotDurationMs;
|
|
2129
2181
|
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
]);
|
|
2182
|
+
const lastUpdateHoldings = await this.getVaultHoldings(vaultState, lastUpdateSlot, vaultReservesMap);
|
|
2183
|
+
prevAUM = lastUpdateHoldings.total;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
const slot = currentSlot ? currentSlot : await this.getConnection().getSlot('confirmed');
|
|
2136
2187
|
|
|
2137
|
-
const
|
|
2188
|
+
const currentHoldings = await this.getVaultHoldings(vaultState, slot, vaultReservesMap);
|
|
2189
|
+
const earnedInterest = currentHoldings.total.sub(prevAUM);
|
|
2138
2190
|
|
|
2139
2191
|
return {
|
|
2140
2192
|
holdings: currentHoldings,
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
PerformanceFeeBps,
|
|
54
54
|
} from './idl_codegen_kamino_vault/types/VaultConfigField';
|
|
55
55
|
import { getAccountOwner } from './utils/rpc';
|
|
56
|
+
import { printHoldings } from './classes/types_utils';
|
|
56
57
|
|
|
57
58
|
dotenv.config({
|
|
58
59
|
path: `.env${process.env.ENV ? '.' + process.env.ENV : ''}`,
|
|
@@ -293,6 +294,42 @@ async function main() {
|
|
|
293
294
|
mode === 'execute' && console.log('Pending admin updated:', updateVaultPendingAdminSig);
|
|
294
295
|
});
|
|
295
296
|
|
|
297
|
+
commands
|
|
298
|
+
.command('update-vault-config')
|
|
299
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
300
|
+
.requiredOption('--field <string>', 'The field to update')
|
|
301
|
+
.requiredOption('--value <string>', 'The value to update the field to')
|
|
302
|
+
.requiredOption(
|
|
303
|
+
`--mode <string>`,
|
|
304
|
+
'simulate - to print txn simulation, inspect - to get txn simulation in explorer, execute - execute txn, multisig - to get bs58 txn for multisig usage'
|
|
305
|
+
)
|
|
306
|
+
.option(`--staging`, 'If true, will use the staging programs')
|
|
307
|
+
.option(`--multisig <string>`, 'If using multisig mode this is required, otherwise will be ignored')
|
|
308
|
+
.action(async ({ vault, field, value, mode, staging, multisig }) => {
|
|
309
|
+
const env = initializeClient(mode === 'multisig', staging);
|
|
310
|
+
const vaultAddress = new PublicKey(vault);
|
|
311
|
+
|
|
312
|
+
if (mode === 'multisig' && !multisig) {
|
|
313
|
+
throw new Error('If using multisig mode, multisig is required');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
317
|
+
|
|
318
|
+
const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
319
|
+
const instructions = await kaminoManager.updateVaultConfigIxs(kaminoVault, field, value);
|
|
320
|
+
|
|
321
|
+
const updateVaultPendingAdminSig = await processTxn(
|
|
322
|
+
env.client,
|
|
323
|
+
env.payer,
|
|
324
|
+
[instructions.updateVaultConfigIx, ...instructions.updateLUTIxs],
|
|
325
|
+
mode,
|
|
326
|
+
2500,
|
|
327
|
+
[]
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
mode === 'execute' && console.log('Pending admin updated:', updateVaultPendingAdminSig);
|
|
331
|
+
});
|
|
332
|
+
|
|
296
333
|
commands
|
|
297
334
|
.command('update-vault-mgmt-fee')
|
|
298
335
|
.requiredOption('--vault <string>', 'Vault address')
|
|
@@ -796,8 +833,8 @@ async function main() {
|
|
|
796
833
|
const vaultState = await new KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
797
834
|
const vaultOverview = await kaminoManager.getVaultOverview(
|
|
798
835
|
vaultState,
|
|
799
|
-
|
|
800
|
-
|
|
836
|
+
new Decimal(1.0),
|
|
837
|
+
await env.connection.getSlot('confirmed')
|
|
801
838
|
);
|
|
802
839
|
|
|
803
840
|
console.log('vaultOverview', vaultOverview);
|
|
@@ -890,8 +927,11 @@ async function main() {
|
|
|
890
927
|
const sharesIssued = new Decimal(vaultState.sharesIssued.toString()!).div(
|
|
891
928
|
new Decimal(vaultState.sharesMintDecimals.toString())
|
|
892
929
|
);
|
|
930
|
+
|
|
931
|
+
console.log('farm', vaultState.vaultFarm.toString());
|
|
932
|
+
console.log('Name: ', kaminoManager.getDecodedVaultName(kaminoVault.state!));
|
|
893
933
|
console.log('Shares issued: ', sharesIssued);
|
|
894
|
-
|
|
934
|
+
printHoldings(holdings);
|
|
895
935
|
console.log(`Tokens per share for vault ${vaultAddress.toBase58()}: ${tokensPerShare}`);
|
|
896
936
|
});
|
|
897
937
|
|
|
@@ -937,7 +977,6 @@ async function main() {
|
|
|
937
977
|
const simulatedHoldings = await kaminoManager.calculateSimulatedHoldingsWithInterest(vaultState);
|
|
938
978
|
|
|
939
979
|
console.log('Simulated holdings with interest', simulatedHoldings);
|
|
940
|
-
|
|
941
980
|
const simulatedFees = await kaminoManager.calculateSimulatedFees(vaultState, simulatedHoldings);
|
|
942
981
|
|
|
943
982
|
console.log('Simulated fees', simulatedFees);
|