@kamino-finance/klend-sdk 5.2.12 → 5.2.14
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 +36 -7
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +41 -7
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/obligation.d.ts +2 -0
- package/dist/classes/obligation.d.ts.map +1 -1
- package/dist/classes/obligation.js +12 -6
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/types.d.ts +23 -0
- package/dist/classes/types.d.ts.map +1 -0
- package/dist/classes/types.js +3 -0
- package/dist/classes/types.js.map +1 -0
- package/dist/classes/vault.d.ts +45 -9
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +349 -20
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +100 -16
- package/dist/client_kamino_manager.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.d.ts +4 -2
- package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.js +45 -52
- package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.d.ts +7 -0
- package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.js +13 -3
- package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +57 -10
- package/src/classes/obligation.ts +15 -6
- package/src/classes/types.ts +27 -0
- package/src/classes/vault.ts +511 -26
- package/src/client_kamino_manager.ts +174 -19
- package/src/lending_operations/repay_with_collateral_calcs.ts +55 -61
- package/src/lending_operations/repay_with_collateral_operations.ts +24 -4
- package/src/leverage/operations.ts +1 -1
package/dist/classes/vault.js
CHANGED
|
@@ -10,6 +10,7 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
10
10
|
const spl_token_1 = require("@solana/spl-token");
|
|
11
11
|
const lib_1 = require("../lib");
|
|
12
12
|
const instructions_1 = require("../idl_codegen_kamino_vault/instructions");
|
|
13
|
+
const types_1 = require("../idl_codegen_kamino_vault/types");
|
|
13
14
|
const accounts_1 = require("../idl_codegen_kamino_vault/accounts");
|
|
14
15
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
15
16
|
const utils_1 = require("./utils");
|
|
@@ -21,6 +22,7 @@ const fraction_1 = require("./fraction");
|
|
|
21
22
|
const utils_2 = require("../utils");
|
|
22
23
|
const bs58_1 = __importDefault(require("bs58"));
|
|
23
24
|
const rpc_1 = require("../utils/rpc");
|
|
25
|
+
const kliquidity_sdk_1 = require("@kamino-finance/kliquidity-sdk");
|
|
24
26
|
exports.kaminoVaultId = new web3_js_1.PublicKey('kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr');
|
|
25
27
|
exports.kaminoVaultStagingId = new web3_js_1.PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuYMFMTsE77FiRsL2');
|
|
26
28
|
const TOKEN_VAULT_SEED = 'token_vault';
|
|
@@ -51,7 +53,7 @@ class KaminoVaultClient {
|
|
|
51
53
|
* 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
|
|
52
54
|
* @param vaultConfig - the config object used to create a vault
|
|
53
55
|
* @returns vault - keypair, should be used to sign the transaction which creates the vault account
|
|
54
|
-
* @returns
|
|
56
|
+
* @returns vault: the keypair of the vault, used to sign the initialization transaction; initVaultIxs: a struct with ixs to initialize the vault and its lookup table + populateLUTIxs, a list to populate the lookup table which has to be executed in a separate transaction
|
|
55
57
|
*/
|
|
56
58
|
async createVaultIxs(vaultConfig) {
|
|
57
59
|
const vaultState = web3_js_1.Keypair.generate();
|
|
@@ -79,8 +81,38 @@ class KaminoVaultClient {
|
|
|
79
81
|
sharesTokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
80
82
|
};
|
|
81
83
|
const initVaultIx = (0, instructions_1.initVault)(initVaultAccounts, this._kaminoVaultProgramId);
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
+
// create and set up the vault lookup table
|
|
85
|
+
const slot = await this._connection.getSlot();
|
|
86
|
+
const [createLUTIx, lut] = this.getInitLookupTableIx(vaultConfig.admin, slot);
|
|
87
|
+
const accountsToBeInserted = [
|
|
88
|
+
vaultConfig.admin,
|
|
89
|
+
vaultState.publicKey,
|
|
90
|
+
vaultConfig.tokenMint,
|
|
91
|
+
vaultConfig.tokenMintProgramId,
|
|
92
|
+
baseVaultAuthority,
|
|
93
|
+
sharesMint,
|
|
94
|
+
web3_js_1.SystemProgram.programId,
|
|
95
|
+
web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
96
|
+
spl_token_1.TOKEN_PROGRAM_ID,
|
|
97
|
+
this._kaminoLendProgramId,
|
|
98
|
+
web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
99
|
+
];
|
|
100
|
+
const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(vaultConfig.admin, lut, accountsToBeInserted, []);
|
|
101
|
+
const setLUTIx = this.updateUninitialisedVaultConfigIx(vaultConfig.admin, vaultState.publicKey, new types_1.VaultConfigField.LookupTable(), lut.toString());
|
|
102
|
+
const ixns = [createVaultIx, initVaultIx, createLUTIx, setLUTIx];
|
|
103
|
+
if (vaultConfig.getPerformanceFeeBps() > 0) {
|
|
104
|
+
const setPerformanceFeeIx = this.updateUninitialisedVaultConfigIx(vaultConfig.admin, vaultState.publicKey, new types_1.VaultConfigField.PerformanceFeeBps(), vaultConfig.getPerformanceFeeBps().toString());
|
|
105
|
+
ixns.push(setPerformanceFeeIx);
|
|
106
|
+
}
|
|
107
|
+
if (vaultConfig.getManagementFeeBps() > 0) {
|
|
108
|
+
const setManagementFeeIx = this.updateUninitialisedVaultConfigIx(vaultConfig.admin, vaultState.publicKey, new types_1.VaultConfigField.ManagementFeeBps(), vaultConfig.getManagementFeeBps().toString());
|
|
109
|
+
ixns.push(setManagementFeeIx);
|
|
110
|
+
}
|
|
111
|
+
if (vaultConfig.name && vaultConfig.name.length > 0) {
|
|
112
|
+
const setNameIx = this.updateUninitialisedVaultConfigIx(vaultConfig.admin, vaultState.publicKey, new types_1.VaultConfigField.Name(), vaultConfig.name);
|
|
113
|
+
ixns.push(setNameIx);
|
|
114
|
+
}
|
|
115
|
+
return { vault: vaultState, initVaultIxs: { initVaultIxs: ixns, populateLUTIxs: insertIntoLUTIxs } };
|
|
84
116
|
}
|
|
85
117
|
/**
|
|
86
118
|
* This method updates the vault reserve allocation cofnig for an exiting vault reserve, or adds a new reserve to the vault if it does not exist.
|
|
@@ -107,16 +139,29 @@ class KaminoVaultClient {
|
|
|
107
139
|
weight: new anchor_1.BN(reserveAllocationConfig.targetAllocationWeight),
|
|
108
140
|
cap: new anchor_1.BN(reserveAllocationConfig.getAllocationCapLamports().floor().toString()),
|
|
109
141
|
};
|
|
110
|
-
|
|
142
|
+
const updateReserveAllocationIx = (0, instructions_1.updateReserveAllocation)(updateReserveAllocationArgs, updateReserveAllocationAccounts, this._kaminoVaultProgramId);
|
|
143
|
+
const accountsToAddToLUT = [
|
|
144
|
+
reserveAllocationConfig.getReserveAddress(),
|
|
145
|
+
cTokenVault,
|
|
146
|
+
...this.getReserveAccountsToInsertInLut(reserveState),
|
|
147
|
+
];
|
|
148
|
+
const lendingMarketAuth = (0, utils_2.lendingMarketAuthPda)(reserveState.lendingMarket, this._kaminoLendProgramId)[0];
|
|
149
|
+
accountsToAddToLUT.push(lendingMarketAuth);
|
|
150
|
+
const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(vaultState.adminAuthority, vaultState.vaultLookupTable, accountsToAddToLUT);
|
|
151
|
+
const updateReserveAllocationIxs = {
|
|
152
|
+
updateReserveAllocationIx,
|
|
153
|
+
updateLUTIxs: insertIntoLUTIxs,
|
|
154
|
+
};
|
|
155
|
+
return updateReserveAllocationIxs;
|
|
111
156
|
}
|
|
112
157
|
/**
|
|
113
|
-
*
|
|
114
|
-
* @param vault
|
|
115
|
-
* @param mode
|
|
116
|
-
* @param value
|
|
117
|
-
* @returns
|
|
158
|
+
* Update a field of the vault. If the field is a pubkey it will return an extra instruction to add that account into the lookup table
|
|
159
|
+
* @param vault the vault to update
|
|
160
|
+
* @param mode the field to update (based on VaultConfigFieldKind enum)
|
|
161
|
+
* @param value the value to update the field with
|
|
162
|
+
* @returns a struct that contains the instruction to update the field and an optional list of instructions to update the lookup table
|
|
118
163
|
*/
|
|
119
|
-
async
|
|
164
|
+
async updateVaultConfigIxs(vault, mode, value) {
|
|
120
165
|
const vaultState = await vault.getState(this.getConnection());
|
|
121
166
|
const updateVaultConfigAccs = {
|
|
122
167
|
adminAuthority: vaultState.adminAuthority,
|
|
@@ -128,8 +173,14 @@ class KaminoVaultClient {
|
|
|
128
173
|
data: Buffer.from([0]),
|
|
129
174
|
};
|
|
130
175
|
if (isNaN(+value)) {
|
|
131
|
-
|
|
132
|
-
|
|
176
|
+
if (mode.kind === new types_1.VaultConfigField.Name().kind) {
|
|
177
|
+
const data = Array.from(this.encodeVaultName(value));
|
|
178
|
+
updateVaultConfigArgs.data = Buffer.from(data);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const data = new web3_js_1.PublicKey(value);
|
|
182
|
+
updateVaultConfigArgs.data = data.toBuffer();
|
|
183
|
+
}
|
|
133
184
|
}
|
|
134
185
|
else {
|
|
135
186
|
const buffer = Buffer.alloc(8);
|
|
@@ -155,6 +206,51 @@ class KaminoVaultClient {
|
|
|
155
206
|
const updateVaultConfigIx = (0, instructions_1.updateVaultConfig)(updateVaultConfigArgs, updateVaultConfigAccs, this._kaminoVaultProgramId);
|
|
156
207
|
updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesAccountMetas);
|
|
157
208
|
updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesLendingMarkets);
|
|
209
|
+
const updateLUTIxs = [];
|
|
210
|
+
if (mode.kind === new types_1.VaultConfigField.PendingVaultAdmin().kind || mode.kind === new types_1.VaultConfigField.Farm().kind) {
|
|
211
|
+
const newPubkey = new web3_js_1.PublicKey(value);
|
|
212
|
+
const insertIntoLutIxs = await this.insertIntoLookupTableIxs(vaultState.adminAuthority, vaultState.vaultLookupTable, [newPubkey]);
|
|
213
|
+
updateLUTIxs.push(...insertIntoLutIxs);
|
|
214
|
+
}
|
|
215
|
+
const updateVaultConfigIxs = {
|
|
216
|
+
updateVaultConfigIx,
|
|
217
|
+
updateLUTIxs,
|
|
218
|
+
};
|
|
219
|
+
return updateVaultConfigIxs;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* This method updates the vault config for a vault that
|
|
223
|
+
* @param vault - address of vault to be updated
|
|
224
|
+
* @param mode - the field to be updated
|
|
225
|
+
* @param value - the new value for the field to be updated (number or pubkey)
|
|
226
|
+
* @returns - a list of instructions
|
|
227
|
+
*/
|
|
228
|
+
updateUninitialisedVaultConfigIx(admin, vault, mode, value) {
|
|
229
|
+
const updateVaultConfigAccs = {
|
|
230
|
+
adminAuthority: admin,
|
|
231
|
+
vaultState: vault,
|
|
232
|
+
klendProgram: this._kaminoLendProgramId,
|
|
233
|
+
};
|
|
234
|
+
const updateVaultConfigArgs = {
|
|
235
|
+
entry: mode,
|
|
236
|
+
data: Buffer.from([0]),
|
|
237
|
+
};
|
|
238
|
+
if (isNaN(+value)) {
|
|
239
|
+
if (mode.kind === new types_1.VaultConfigField.Name().kind) {
|
|
240
|
+
const data = Array.from(this.encodeVaultName(value));
|
|
241
|
+
updateVaultConfigArgs.data = Buffer.from(data);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
const data = new web3_js_1.PublicKey(value);
|
|
245
|
+
updateVaultConfigArgs.data = data.toBuffer();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
const buffer = Buffer.alloc(8);
|
|
250
|
+
buffer.writeBigUInt64LE(BigInt(value.toString()));
|
|
251
|
+
updateVaultConfigArgs.data = buffer;
|
|
252
|
+
}
|
|
253
|
+
const updateVaultConfigIx = (0, instructions_1.updateVaultConfig)(updateVaultConfigArgs, updateVaultConfigAccs, this._kaminoVaultProgramId);
|
|
158
254
|
return updateVaultConfigIx;
|
|
159
255
|
}
|
|
160
256
|
/**
|
|
@@ -162,13 +258,28 @@ class KaminoVaultClient {
|
|
|
162
258
|
* @param vault - vault to change the ownership for
|
|
163
259
|
* @returns - an instruction to be used to be executed
|
|
164
260
|
*/
|
|
165
|
-
async
|
|
261
|
+
async acceptVaultOwnershipIxs(vault) {
|
|
166
262
|
const vaultState = await vault.getState(this.getConnection());
|
|
167
263
|
const acceptOwneshipAccounts = {
|
|
168
264
|
pendingAdmin: vaultState.pendingAdmin,
|
|
169
265
|
vaultState: vault.address,
|
|
170
266
|
};
|
|
171
|
-
|
|
267
|
+
const acceptVaultOwnershipIx = (0, instructions_1.updateAdmin)(acceptOwneshipAccounts, this._kaminoVaultProgramId);
|
|
268
|
+
// read the current LUT and create a new one for the new admin and backfill it
|
|
269
|
+
const accountsInExistentLUT = (await this.getAccountsInLUT(vaultState.vaultLookupTable)).filter((account) => !account.equals(vaultState.adminAuthority));
|
|
270
|
+
const LUTIxs = [];
|
|
271
|
+
const [initNewLUTIx, newLUT] = this.getInitLookupTableIx(vaultState.pendingAdmin, await this._connection.getSlot());
|
|
272
|
+
LUTIxs.push(initNewLUTIx);
|
|
273
|
+
const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(vaultState.pendingAdmin, newLUT, accountsInExistentLUT);
|
|
274
|
+
LUTIxs.push(...insertIntoLUTIxs);
|
|
275
|
+
const updateVaultConfigIxs = await this.updateVaultConfigIxs(vault, new types_1.VaultConfigField.LookupTable(), newLUT.toString());
|
|
276
|
+
LUTIxs.push(updateVaultConfigIxs.updateVaultConfigIx);
|
|
277
|
+
LUTIxs.push(...updateVaultConfigIxs.updateLUTIxs);
|
|
278
|
+
const acceptVaultOwnershipIxs = {
|
|
279
|
+
acceptVaultOwnershipIx,
|
|
280
|
+
updateLUTIxs: LUTIxs,
|
|
281
|
+
};
|
|
282
|
+
return acceptVaultOwnershipIxs;
|
|
172
283
|
}
|
|
173
284
|
/**
|
|
174
285
|
* This function creates the instruction for the admin to give up a part of the pending fees (which will be accounted as part of the vault)
|
|
@@ -322,6 +433,32 @@ class KaminoVaultClient {
|
|
|
322
433
|
* @returns an array of instructions to be executed
|
|
323
434
|
*/
|
|
324
435
|
async withdrawIxs(user, vault, shareAmount, slot, vaultReservesMap) {
|
|
436
|
+
const vaultState = await vault.getState(this._connection);
|
|
437
|
+
const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
|
|
438
|
+
// if the vault has allocations withdraw otherwise wtihdraw from available ix
|
|
439
|
+
const vaultAllocation = vaultState.vaultAllocationStrategy.find((allocation) => ~allocation.reserve.equals(web3_js_1.PublicKey.default));
|
|
440
|
+
if (vaultAllocation) {
|
|
441
|
+
return this.wihdrdrawWithReserveIxns(user, kaminoVault, shareAmount, slot, vaultReservesMap);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
return this.withdrawFromAvailableIxns(user, kaminoVault, shareAmount);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
async withdrawFromAvailableIxns(user, vault, shareAmount) {
|
|
448
|
+
const vaultState = await vault.getState(this._connection);
|
|
449
|
+
const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
|
|
450
|
+
const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user);
|
|
451
|
+
const [{ ata: userTokenAta, createAtaIx }] = (0, utils_2.createAtasIdempotent)(user, [
|
|
452
|
+
{
|
|
453
|
+
mint: vaultState.tokenMint,
|
|
454
|
+
tokenProgram: vaultState.tokenProgram,
|
|
455
|
+
},
|
|
456
|
+
]);
|
|
457
|
+
const shareLamportsToWithdraw = (0, kliquidity_sdk_1.collToLamportsDecimal)(shareAmount, vaultState.sharesMintDecimals.toNumber());
|
|
458
|
+
const withdrawFromAvailableIxn = await this.withdrawFromAvailableIxn(user, kaminoVault, vaultState, userSharesAta, userTokenAta, shareLamportsToWithdraw);
|
|
459
|
+
return [createAtaIx, withdrawFromAvailableIxn];
|
|
460
|
+
}
|
|
461
|
+
async wihdrdrawWithReserveIxns(user, vault, shareAmount, slot, vaultReservesMap) {
|
|
325
462
|
const vaultState = await vault.getState(this._connection);
|
|
326
463
|
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
327
464
|
const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user);
|
|
@@ -396,7 +533,7 @@ class KaminoVaultClient {
|
|
|
396
533
|
* @param reserve - reserve to invest into or disinvest from
|
|
397
534
|
* @returns - an array of invest instructions for each invest action required for the vault reserves
|
|
398
535
|
*/
|
|
399
|
-
async investSingleReserveIxs(payer, vault, reserve) {
|
|
536
|
+
async investSingleReserveIxs(payer, vault, reserve, vaultReservesMap) {
|
|
400
537
|
const vaultState = await vault.getState(this._connection);
|
|
401
538
|
const cTokenVault = getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId);
|
|
402
539
|
const lendingMarketAuth = (0, utils_2.lendingMarketAuthPda)(reserve.state.lendingMarket, this._kaminoLendProgramId)[0];
|
|
@@ -425,12 +562,38 @@ class KaminoVaultClient {
|
|
|
425
562
|
};
|
|
426
563
|
const investIx = (0, instructions_1.invest)(investAccounts, this._kaminoVaultProgramId);
|
|
427
564
|
const vaultReserves = this.getVaultReserves(vaultState);
|
|
428
|
-
const
|
|
429
|
-
|
|
565
|
+
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
566
|
+
let vaultReservesAccountMetas = [];
|
|
567
|
+
let vaultReservesLendingMarkets = [];
|
|
568
|
+
vaultReserves.forEach((reserve) => {
|
|
569
|
+
const reserveState = vaultReservesState.get(reserve);
|
|
570
|
+
if (reserveState === undefined) {
|
|
571
|
+
throw new Error(`Reserve ${reserve.toBase58()} not found`);
|
|
572
|
+
}
|
|
573
|
+
vaultReservesAccountMetas = vaultReservesAccountMetas.concat([
|
|
574
|
+
{ pubkey: reserve, isSigner: false, isWritable: true },
|
|
575
|
+
]);
|
|
576
|
+
vaultReservesLendingMarkets = vaultReservesLendingMarkets.concat([
|
|
577
|
+
{ pubkey: reserveState.state.lendingMarket, isSigner: false, isWritable: false },
|
|
578
|
+
]);
|
|
430
579
|
});
|
|
431
580
|
investIx.keys = investIx.keys.concat(vaultReservesAccountMetas);
|
|
581
|
+
investIx.keys = investIx.keys.concat(vaultReservesLendingMarkets);
|
|
432
582
|
return [createAtaIx, investIx];
|
|
433
583
|
}
|
|
584
|
+
encodeVaultName(token) {
|
|
585
|
+
const maxArray = new Uint8Array(40);
|
|
586
|
+
const s = new TextEncoder().encode(token);
|
|
587
|
+
maxArray.set(s);
|
|
588
|
+
return maxArray;
|
|
589
|
+
}
|
|
590
|
+
decodeVaultName(token) {
|
|
591
|
+
const maxArray = new Uint8Array(token);
|
|
592
|
+
let s = new TextDecoder().decode(maxArray);
|
|
593
|
+
// Remove trailing zeros and spaces
|
|
594
|
+
s = s.replace(/[\0 ]+$/, '');
|
|
595
|
+
return s;
|
|
596
|
+
}
|
|
434
597
|
withdrawIxn(user, vault, vaultState, marketAddress, reserve, userSharesAta, userTokenAta, shareAmountLamports, vaultReservesState) {
|
|
435
598
|
const lendingMarketAuth = (0, utils_2.lendingMarketAuthPda)(marketAddress, this._kaminoLendProgramId)[0];
|
|
436
599
|
const withdrawAccounts = {
|
|
@@ -482,6 +645,25 @@ class KaminoVaultClient {
|
|
|
482
645
|
withdrawIxn.keys = withdrawIxn.keys.concat(vaultReservesLendingMarkets);
|
|
483
646
|
return withdrawIxn;
|
|
484
647
|
}
|
|
648
|
+
async withdrawFromAvailableIxn(user, vault, vaultState, userSharesAta, userTokenAta, shareAmountLamports) {
|
|
649
|
+
const withdrawFromAvailableAccounts = {
|
|
650
|
+
user,
|
|
651
|
+
vaultState: vault.address,
|
|
652
|
+
tokenVault: vaultState.tokenVault,
|
|
653
|
+
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
654
|
+
userTokenAta: userTokenAta,
|
|
655
|
+
tokenMint: vaultState.tokenMint,
|
|
656
|
+
userSharesAta: userSharesAta,
|
|
657
|
+
sharesMint: vaultState.sharesMint,
|
|
658
|
+
tokenProgram: vaultState.tokenProgram,
|
|
659
|
+
sharesTokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
660
|
+
klendProgram: this._kaminoLendProgramId,
|
|
661
|
+
};
|
|
662
|
+
const withdrawFromAvailableArgs = {
|
|
663
|
+
sharesAmount: new anchor_1.BN(shareAmountLamports.toString()),
|
|
664
|
+
};
|
|
665
|
+
return (0, instructions_1.withdrawFromAvailable)(withdrawFromAvailableArgs, withdrawFromAvailableAccounts, this._kaminoVaultProgramId);
|
|
666
|
+
}
|
|
485
667
|
async withdrawPendingFeesIxn(vault, vaultState, marketAddress, reserve, adminTokenAta) {
|
|
486
668
|
const lendingMarketAuth = (0, utils_2.lendingMarketAuthPda)(marketAddress, this._kaminoLendProgramId)[0];
|
|
487
669
|
const withdrawPendingFeesAccounts = {
|
|
@@ -524,6 +706,150 @@ class KaminoVaultClient {
|
|
|
524
706
|
withdrawPendingFeesIxn.keys = withdrawPendingFeesIxn.keys.concat(vaultReservesLendingMarkets);
|
|
525
707
|
return withdrawPendingFeesIxn;
|
|
526
708
|
}
|
|
709
|
+
/**
|
|
710
|
+
* Sync a vault for lookup table; create and set the LUT for the vault if needed and fill it with all the needed accounts
|
|
711
|
+
* @param vault the vault to sync and set the LUT for if needed
|
|
712
|
+
* @param vaultReserves optional; the state of the reserves in the vault allocation
|
|
713
|
+
* @returns a struct that contains a list of ix to create the LUT and assign it to the vault if needed + a list of ixs to insert all the accounts in the LUT
|
|
714
|
+
*/
|
|
715
|
+
async syncVaultLookupTable(vault, vaultReserves) {
|
|
716
|
+
const vaultState = await vault.getState(this._connection);
|
|
717
|
+
const allAccountsToBeInserted = [
|
|
718
|
+
vault.address,
|
|
719
|
+
vaultState.adminAuthority,
|
|
720
|
+
vaultState.baseVaultAuthority,
|
|
721
|
+
vaultState.tokenMint,
|
|
722
|
+
vaultState.tokenVault,
|
|
723
|
+
vaultState.sharesMint,
|
|
724
|
+
vaultState.tokenProgram,
|
|
725
|
+
this._kaminoLendProgramId,
|
|
726
|
+
];
|
|
727
|
+
vaultState.vaultAllocationStrategy.forEach((allocation) => {
|
|
728
|
+
allAccountsToBeInserted.push(allocation.reserve);
|
|
729
|
+
allAccountsToBeInserted.push(allocation.ctokenVault);
|
|
730
|
+
});
|
|
731
|
+
if (vaultReserves) {
|
|
732
|
+
vaultReserves.forEach((reserve) => {
|
|
733
|
+
allAccountsToBeInserted.push(reserve.state.lendingMarket);
|
|
734
|
+
allAccountsToBeInserted.push(reserve.state.farmCollateral);
|
|
735
|
+
allAccountsToBeInserted.push(reserve.state.farmDebt);
|
|
736
|
+
allAccountsToBeInserted.push(reserve.state.liquidity.supplyVault);
|
|
737
|
+
allAccountsToBeInserted.push(reserve.state.liquidity.feeVault);
|
|
738
|
+
allAccountsToBeInserted.push(reserve.state.collateral.mintPubkey);
|
|
739
|
+
allAccountsToBeInserted.push(reserve.state.collateral.supplyVault);
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
const vaultReservesState = await this.loadVaultReserves(vaultState);
|
|
744
|
+
vaultReservesState.forEach((reserve) => {
|
|
745
|
+
allAccountsToBeInserted.push(reserve.state.lendingMarket);
|
|
746
|
+
allAccountsToBeInserted.push(reserve.state.farmCollateral);
|
|
747
|
+
allAccountsToBeInserted.push(reserve.state.farmDebt);
|
|
748
|
+
allAccountsToBeInserted.push(reserve.state.liquidity.supplyVault);
|
|
749
|
+
allAccountsToBeInserted.push(reserve.state.liquidity.feeVault);
|
|
750
|
+
allAccountsToBeInserted.push(reserve.state.collateral.mintPubkey);
|
|
751
|
+
allAccountsToBeInserted.push(reserve.state.collateral.supplyVault);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
if (!vaultState.vaultFarm.equals(web3_js_1.PublicKey.default)) {
|
|
755
|
+
allAccountsToBeInserted.push(vaultState.vaultFarm);
|
|
756
|
+
}
|
|
757
|
+
const setupLUTIfNeededIxs = [];
|
|
758
|
+
let lut = vaultState.vaultLookupTable;
|
|
759
|
+
if (lut.equals(web3_js_1.PublicKey.default)) {
|
|
760
|
+
const recentSlot = await this._connection.getSlot();
|
|
761
|
+
const [ixn, address] = this.getInitLookupTableIx(vaultState.adminAuthority, recentSlot);
|
|
762
|
+
setupLUTIfNeededIxs.push(ixn);
|
|
763
|
+
lut = address;
|
|
764
|
+
// set the new LUT for the vault
|
|
765
|
+
const updateVaultConfigIxs = await this.updateVaultConfigIxs(vault, new types_1.VaultConfigField.LookupTable(), lut.toString());
|
|
766
|
+
setupLUTIfNeededIxs.push(updateVaultConfigIxs.updateVaultConfigIx);
|
|
767
|
+
}
|
|
768
|
+
const ixns = [];
|
|
769
|
+
let overridenExistentAccounts = undefined;
|
|
770
|
+
if (vaultState.vaultLookupTable.equals(web3_js_1.PublicKey.default)) {
|
|
771
|
+
overridenExistentAccounts = [];
|
|
772
|
+
}
|
|
773
|
+
ixns.push(...(await this.insertIntoLookupTableIxs(vaultState.adminAuthority, lut, allAccountsToBeInserted, overridenExistentAccounts)));
|
|
774
|
+
return {
|
|
775
|
+
setupLUTIfNeededIxs,
|
|
776
|
+
syncLUTIxs: ixns,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
getInitLookupTableIx(payer, slot) {
|
|
780
|
+
const [ixn, address] = web3_js_1.AddressLookupTableProgram.createLookupTable({
|
|
781
|
+
authority: payer,
|
|
782
|
+
payer,
|
|
783
|
+
recentSlot: slot,
|
|
784
|
+
});
|
|
785
|
+
return [ixn, address];
|
|
786
|
+
}
|
|
787
|
+
getReserveAccountsToInsertInLut(reserveState) {
|
|
788
|
+
return [
|
|
789
|
+
reserveState.lendingMarket,
|
|
790
|
+
reserveState.farmCollateral,
|
|
791
|
+
reserveState.farmDebt,
|
|
792
|
+
reserveState.liquidity.mintPubkey,
|
|
793
|
+
reserveState.liquidity.supplyVault,
|
|
794
|
+
reserveState.liquidity.feeVault,
|
|
795
|
+
reserveState.collateral.mintPubkey,
|
|
796
|
+
reserveState.collateral.supplyVault,
|
|
797
|
+
];
|
|
798
|
+
}
|
|
799
|
+
async insertIntoLookupTableIxs(payer, lookupTable, keys, accountsInLUT) {
|
|
800
|
+
let lutContents = accountsInLUT;
|
|
801
|
+
if (!accountsInLUT) {
|
|
802
|
+
lutContents = await this.getAccountsInLUT(lookupTable);
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
lutContents = accountsInLUT;
|
|
806
|
+
}
|
|
807
|
+
const missingAccounts = keys.filter((key) => !lutContents.includes(key) && !key.equals(web3_js_1.PublicKey.default));
|
|
808
|
+
// deduplicate missing accounts and remove default accounts and convert it back to an array
|
|
809
|
+
const missingAccountsList = new utils_2.PublicKeySet(missingAccounts).toArray();
|
|
810
|
+
const chunkSize = 20;
|
|
811
|
+
const ixns = [];
|
|
812
|
+
for (let i = 0; i < missingAccountsList.length; i += chunkSize) {
|
|
813
|
+
const chunk = missingAccountsList.slice(i, i + chunkSize);
|
|
814
|
+
const ixn = web3_js_1.AddressLookupTableProgram.extendLookupTable({
|
|
815
|
+
lookupTable,
|
|
816
|
+
authority: payer,
|
|
817
|
+
payer,
|
|
818
|
+
addresses: chunk,
|
|
819
|
+
});
|
|
820
|
+
ixns.push(ixn);
|
|
821
|
+
}
|
|
822
|
+
return ixns;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
*
|
|
826
|
+
* @param connection
|
|
827
|
+
* @param lookupTable
|
|
828
|
+
* @returns
|
|
829
|
+
*/
|
|
830
|
+
async getAccountsInLUT(lookupTable) {
|
|
831
|
+
const lutState = await this._connection.getAddressLookupTable(lookupTable);
|
|
832
|
+
if (!lutState || !lutState.value) {
|
|
833
|
+
throw new Error(`Lookup table ${lookupTable} not found`);
|
|
834
|
+
}
|
|
835
|
+
return lutState.value.state.addresses;
|
|
836
|
+
}
|
|
837
|
+
deactivateLookupTableIx(payer, lookupTable) {
|
|
838
|
+
const ixn = web3_js_1.AddressLookupTableProgram.deactivateLookupTable({
|
|
839
|
+
authority: payer,
|
|
840
|
+
lookupTable: lookupTable,
|
|
841
|
+
});
|
|
842
|
+
return ixn;
|
|
843
|
+
}
|
|
844
|
+
/// this require the LUT to be deactivated at least 500 blocks before
|
|
845
|
+
closeLookupTableIx(payer, lookupTable) {
|
|
846
|
+
const ixn = web3_js_1.AddressLookupTableProgram.closeLookupTable({
|
|
847
|
+
authority: payer,
|
|
848
|
+
recipient: payer,
|
|
849
|
+
lookupTable: lookupTable,
|
|
850
|
+
});
|
|
851
|
+
return ixn;
|
|
852
|
+
}
|
|
527
853
|
/**
|
|
528
854
|
* This method returns the user shares balance for a given vault
|
|
529
855
|
* @param user - user to calculate the shares balance for
|
|
@@ -1066,18 +1392,21 @@ class KaminoVaultConfig {
|
|
|
1066
1392
|
performanceFeeRate;
|
|
1067
1393
|
/** The management fee rate of the vault, expressed as a decimal */
|
|
1068
1394
|
managementFeeRate;
|
|
1395
|
+
/** The name to be stored on cain for the vault (max 40 characters). */
|
|
1396
|
+
name;
|
|
1069
1397
|
constructor(args) {
|
|
1070
1398
|
this.admin = args.admin;
|
|
1071
1399
|
this.tokenMint = args.tokenMint;
|
|
1072
1400
|
this.performanceFeeRate = args.performanceFeeRate;
|
|
1073
1401
|
this.managementFeeRate = args.managementFeeRate;
|
|
1074
1402
|
this.tokenMintProgramId = args.tokenMintProgramId;
|
|
1403
|
+
this.name = args.name;
|
|
1075
1404
|
}
|
|
1076
1405
|
getPerformanceFeeBps() {
|
|
1077
|
-
return this.performanceFeeRate.mul(
|
|
1406
|
+
return this.performanceFeeRate.mul(100).toNumber();
|
|
1078
1407
|
}
|
|
1079
|
-
|
|
1080
|
-
return this.managementFeeRate.mul(
|
|
1408
|
+
getManagementFeeBps() {
|
|
1409
|
+
return this.managementFeeRate.mul(100).toNumber();
|
|
1081
1410
|
}
|
|
1082
1411
|
}
|
|
1083
1412
|
exports.KaminoVaultConfig = KaminoVaultConfig;
|