@kamino-finance/klend-sdk 5.1.8 → 5.1.10
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.map +1 -1
- package/dist/classes/action.js +5 -4
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts +13 -4
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +13 -2
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/utils.d.ts +2 -1
- package/dist/classes/utils.d.ts.map +1 -1
- package/dist/classes/utils.js +9 -0
- package/dist/classes/utils.js.map +1 -1
- package/dist/classes/vault.d.ts +20 -2
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +68 -22
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +96 -1
- package/dist/client_kamino_manager.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/action.ts +8 -8
- package/src/classes/manager.ts +19 -4
- package/src/classes/utils.ts +12 -1
- package/src/classes/vault.ts +100 -37
- package/src/client_kamino_manager.ts +130 -1
package/src/classes/vault.ts
CHANGED
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
import { TOKEN_PROGRAM_ID, unpackAccount } from '@solana/spl-token';
|
|
14
14
|
import {
|
|
15
15
|
getAssociatedTokenAddress,
|
|
16
|
-
getAtasWithCreateIxnsIfMissing,
|
|
17
16
|
getDepositWsolIxns,
|
|
18
17
|
getTokenOracleData,
|
|
18
|
+
KaminoMarket,
|
|
19
19
|
KaminoReserve,
|
|
20
20
|
lamportsToDecimal,
|
|
21
21
|
LendingMarket,
|
|
@@ -50,15 +50,15 @@ import {
|
|
|
50
50
|
import { VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
|
|
51
51
|
import { VaultState } from '../idl_codegen_kamino_vault/accounts';
|
|
52
52
|
import Decimal from 'decimal.js';
|
|
53
|
-
import { numberToLamportsDecimal, parseTokenSymbol } from './utils';
|
|
53
|
+
import { getTokenBalanceFromAccountInfoLamports, numberToLamportsDecimal, parseTokenSymbol } from './utils';
|
|
54
54
|
import { deposit } from '../idl_codegen_kamino_vault/instructions';
|
|
55
55
|
import { withdraw } from '../idl_codegen_kamino_vault/instructions';
|
|
56
56
|
import { PROGRAM_ID } from '../idl_codegen/programId';
|
|
57
57
|
import { DEFAULT_RECENT_SLOT_DURATION_MS, ReserveWithAddress } from './reserve';
|
|
58
58
|
import { Fraction } from './fraction';
|
|
59
|
-
import { lendingMarketAuthPda } from '../utils';
|
|
59
|
+
import { createAtasIdempotent, lendingMarketAuthPda } from '../utils';
|
|
60
60
|
import bs58 from 'bs58';
|
|
61
|
-
import { getProgramAccounts } from '../utils/rpc';
|
|
61
|
+
import { getAccountOwner, getProgramAccounts } from '../utils/rpc';
|
|
62
62
|
|
|
63
63
|
export const kaminoVaultId = new PublicKey('kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr');
|
|
64
64
|
export const kaminoVaultStagingId = new PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuYMFMTsE77FiRsL2');
|
|
@@ -306,13 +306,12 @@ export class KaminoVaultClient {
|
|
|
306
306
|
*/
|
|
307
307
|
async withdrawPendingFeesIxs(vault: KaminoVault, slot: number): Promise<TransactionInstruction[]> {
|
|
308
308
|
const vaultState: VaultState = await vault.getState(this.getConnection());
|
|
309
|
-
const {
|
|
309
|
+
const [{ ata: adminTokenAta, createAtaIx }] = createAtasIdempotent(vaultState.adminAuthority, [
|
|
310
310
|
{
|
|
311
311
|
mint: vaultState.tokenMint,
|
|
312
312
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
313
313
|
},
|
|
314
314
|
]);
|
|
315
|
-
const adminTokenAta = atas[0];
|
|
316
315
|
|
|
317
316
|
const tokensToWithdraw = new Fraction(vaultState.pendingFeesSf).toDecimal();
|
|
318
317
|
let tokenLeftToWithdraw = tokensToWithdraw;
|
|
@@ -371,7 +370,7 @@ export class KaminoVaultClient {
|
|
|
371
370
|
})
|
|
372
371
|
);
|
|
373
372
|
|
|
374
|
-
return [
|
|
373
|
+
return [createAtaIx, ...withdrawIxns];
|
|
375
374
|
}
|
|
376
375
|
|
|
377
376
|
// async closeVaultIx(vault: KaminoVault): Promise<TransactionInstruction> {
|
|
@@ -390,6 +389,7 @@ export class KaminoVaultClient {
|
|
|
390
389
|
* @param user - user to deposit
|
|
391
390
|
* @param vault - vault to deposit into
|
|
392
391
|
* @param tokenAmount - token amount to be deposited, in decimals (will be converted in lamports)
|
|
392
|
+
* @param tokenProgramIDOverride - optional param; should be passed if token to be deposited is token22
|
|
393
393
|
* @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
|
|
394
394
|
* @returns - an array of instructions to be used to be executed
|
|
395
395
|
*/
|
|
@@ -397,42 +397,38 @@ export class KaminoVaultClient {
|
|
|
397
397
|
user: PublicKey,
|
|
398
398
|
vault: KaminoVault,
|
|
399
399
|
tokenAmount: Decimal,
|
|
400
|
+
tokenProgramIDOverride?: PublicKey,
|
|
400
401
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
401
402
|
): Promise<TransactionInstruction[]> {
|
|
402
403
|
const vaultState = await vault.getState(this._connection);
|
|
403
404
|
|
|
404
|
-
const
|
|
405
|
+
const tokenProgramID = tokenProgramIDOverride ? tokenProgramIDOverride : TOKEN_PROGRAM_ID;
|
|
406
|
+
const userTokenAta = getAssociatedTokenAddress(vaultState.tokenMint, user, true, tokenProgramID);
|
|
405
407
|
const createAtasIxns: TransactionInstruction[] = [];
|
|
406
408
|
const closeAtasIxns: TransactionInstruction[] = [];
|
|
407
409
|
if (vaultState.tokenMint.equals(WRAPPED_SOL_MINT)) {
|
|
408
|
-
const {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
},
|
|
416
|
-
]
|
|
417
|
-
);
|
|
418
|
-
createAtasIxns.push(...createWsolAtaIxns);
|
|
410
|
+
const [{ ata: wsolAta, createAtaIx: createWsolAtaIxn }] = createAtasIdempotent(user, [
|
|
411
|
+
{
|
|
412
|
+
mint: WRAPPED_SOL_MINT,
|
|
413
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
414
|
+
},
|
|
415
|
+
]);
|
|
416
|
+
createAtasIxns.push(createWsolAtaIxn);
|
|
419
417
|
const depositWsolIxn = getDepositWsolIxns(
|
|
420
418
|
user,
|
|
421
|
-
wsolAta
|
|
419
|
+
wsolAta,
|
|
422
420
|
numberToLamportsDecimal(tokenAmount, vaultState.tokenMintDecimals.toNumber()).ceil()
|
|
423
421
|
);
|
|
424
422
|
createAtasIxns.push(...depositWsolIxn);
|
|
425
423
|
}
|
|
426
424
|
|
|
427
|
-
const {
|
|
425
|
+
const [{ ata: userSharesAta, createAtaIx: createSharesAtaIxns }] = createAtasIdempotent(user, [
|
|
428
426
|
{
|
|
429
427
|
mint: vaultState.sharesMint,
|
|
430
428
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
431
429
|
},
|
|
432
430
|
]);
|
|
433
|
-
createAtasIxns.push(
|
|
434
|
-
|
|
435
|
-
const userSharesAta = atas[0];
|
|
431
|
+
createAtasIxns.push(createSharesAtaIxns);
|
|
436
432
|
|
|
437
433
|
const depoistAccounts: DepositAccounts = {
|
|
438
434
|
user: user,
|
|
@@ -443,7 +439,7 @@ export class KaminoVaultClient {
|
|
|
443
439
|
sharesMint: vaultState.sharesMint,
|
|
444
440
|
tokenAta: userTokenAta,
|
|
445
441
|
userSharesAta: userSharesAta,
|
|
446
|
-
tokenProgram:
|
|
442
|
+
tokenProgram: tokenProgramID,
|
|
447
443
|
instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
448
444
|
klendProgram: this._kaminoLendProgramId,
|
|
449
445
|
sharesTokenProgram: TOKEN_PROGRAM_ID,
|
|
@@ -496,15 +492,14 @@ export class KaminoVaultClient {
|
|
|
496
492
|
const vaultState = await vault.getState(this._connection);
|
|
497
493
|
|
|
498
494
|
const userSharesAta = getAssociatedTokenAddress(vaultState.sharesMint, user);
|
|
499
|
-
const {
|
|
495
|
+
const [{ ata: userTokenAta, createAtaIx }] = createAtasIdempotent(user, [
|
|
500
496
|
{
|
|
501
497
|
mint: vaultState.tokenMint,
|
|
502
498
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
503
499
|
},
|
|
504
500
|
]);
|
|
505
|
-
const userTokenAta = atas[0];
|
|
506
501
|
|
|
507
|
-
const tokensToWithdraw = shareAmount.
|
|
502
|
+
const tokensToWithdraw = shareAmount.mul(await this.getTokensPerShareSingleVault(vault, slot));
|
|
508
503
|
let tokenLeftToWithdraw = tokensToWithdraw;
|
|
509
504
|
|
|
510
505
|
tokenLeftToWithdraw = tokenLeftToWithdraw.sub(new Decimal(vaultState.tokenAvailable.toString()));
|
|
@@ -569,7 +564,7 @@ export class KaminoVaultClient {
|
|
|
569
564
|
})
|
|
570
565
|
);
|
|
571
566
|
|
|
572
|
-
return [
|
|
567
|
+
return [createAtaIx, ...withdrawIxns];
|
|
573
568
|
}
|
|
574
569
|
|
|
575
570
|
/**
|
|
@@ -580,18 +575,20 @@ export class KaminoVaultClient {
|
|
|
580
575
|
*/
|
|
581
576
|
async investAllReservesIxs(payer: PublicKey, vault: KaminoVault): Promise<TransactionInstruction[]> {
|
|
582
577
|
//TODO: Order invest ixns by - invest that removes first, then invest that adds
|
|
583
|
-
|
|
584
578
|
const vaultState = await vault.getState(this._connection);
|
|
585
579
|
const vaultReserves = this.getVaultReserves(vaultState);
|
|
586
|
-
const
|
|
580
|
+
const investIxnsPromises: Promise<TransactionInstruction[]>[] = [];
|
|
587
581
|
for (const reserve of vaultReserves) {
|
|
588
582
|
const reserveState = await Reserve.fetch(this._connection, reserve, this._kaminoLendProgramId);
|
|
589
583
|
if (reserveState === null) {
|
|
590
584
|
throw new Error(`Reserve ${reserve.toBase58()} not found`);
|
|
591
585
|
}
|
|
592
|
-
|
|
586
|
+
const investIxsPromise = this.investSingleReserveIxs(payer, vault, { address: reserve, state: reserveState });
|
|
587
|
+
investIxnsPromises.push(investIxsPromise);
|
|
593
588
|
}
|
|
594
589
|
|
|
590
|
+
const investIxns = await Promise.all(investIxnsPromises).then((ixns) => ixns.flat());
|
|
591
|
+
|
|
595
592
|
return investIxns;
|
|
596
593
|
}
|
|
597
594
|
|
|
@@ -606,13 +603,16 @@ export class KaminoVaultClient {
|
|
|
606
603
|
payer: PublicKey,
|
|
607
604
|
vault: KaminoVault,
|
|
608
605
|
reserve: ReserveWithAddress
|
|
609
|
-
): Promise<TransactionInstruction> {
|
|
606
|
+
): Promise<TransactionInstruction[]> {
|
|
610
607
|
const vaultState = await vault.getState(this._connection);
|
|
611
608
|
|
|
612
609
|
const cTokenVault = getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId);
|
|
613
610
|
const lendingMarketAuth = lendingMarketAuthPda(reserve.state.lendingMarket, this._kaminoLendProgramId)[0];
|
|
614
611
|
|
|
615
|
-
const
|
|
612
|
+
const tokenProgram = await getAccountOwner(this._connection, vaultState.tokenMint);
|
|
613
|
+
const [{ ata: payerTokenAta, createAtaIx }] = createAtasIdempotent(payer, [
|
|
614
|
+
{ mint: vaultState.tokenMint, tokenProgram },
|
|
615
|
+
]);
|
|
616
616
|
|
|
617
617
|
const investAccounts: InvestAccounts = {
|
|
618
618
|
payer,
|
|
@@ -628,7 +628,7 @@ export class KaminoVaultClient {
|
|
|
628
628
|
reserveCollateralMint: reserve.state.collateral.mintPubkey,
|
|
629
629
|
klendProgram: this._kaminoLendProgramId,
|
|
630
630
|
instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
631
|
-
tokenProgram:
|
|
631
|
+
tokenProgram: tokenProgram,
|
|
632
632
|
payerTokenAccount: payerTokenAta,
|
|
633
633
|
tokenMint: vaultState.tokenMint,
|
|
634
634
|
reserveCollateralTokenProgram: TOKEN_PROGRAM_ID,
|
|
@@ -643,7 +643,7 @@ export class KaminoVaultClient {
|
|
|
643
643
|
});
|
|
644
644
|
investIx.keys = investIx.keys.concat(vaultReservesAccountMetas);
|
|
645
645
|
|
|
646
|
-
return investIx;
|
|
646
|
+
return [createAtaIx, investIx];
|
|
647
647
|
}
|
|
648
648
|
|
|
649
649
|
private async withdrawIxn(
|
|
@@ -819,7 +819,7 @@ export class KaminoVaultClient {
|
|
|
819
819
|
} else {
|
|
820
820
|
vaultUserShareBalance.set(
|
|
821
821
|
vaults[index].address,
|
|
822
|
-
|
|
822
|
+
getTokenBalanceFromAccountInfoLamports(userShareAtaAccount).div(
|
|
823
823
|
new Decimal(10).pow(vaults[index].state!.sharesMintDecimals.toString())
|
|
824
824
|
)
|
|
825
825
|
);
|
|
@@ -1047,6 +1047,57 @@ export class KaminoVaultClient {
|
|
|
1047
1047
|
return kaminoReserves;
|
|
1048
1048
|
}
|
|
1049
1049
|
|
|
1050
|
+
/**
|
|
1051
|
+
* This will retrieve all the tokens that can be use as collateral by the users who borrow the token in the vault alongside details about the min and max loan to value ratio
|
|
1052
|
+
* @param vaultState - the vault state to load reserves for
|
|
1053
|
+
*
|
|
1054
|
+
* @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
|
|
1055
|
+
*/
|
|
1056
|
+
async getVaultCollaterals(vaultState: VaultState, slot: number): Promise<PubkeyHashMap<PublicKey, MarketOverview>> {
|
|
1057
|
+
const vaultReservesState = Array.from((await this.loadVaultReserves(vaultState)).values());
|
|
1058
|
+
|
|
1059
|
+
const vaultCollateralsPerReserve: PubkeyHashMap<PublicKey, MarketOverview> = new PubkeyHashMap();
|
|
1060
|
+
|
|
1061
|
+
for (const reserve of vaultReservesState) {
|
|
1062
|
+
const lendingMarket = await KaminoMarket.load(this._connection, reserve.state.lendingMarket, slot);
|
|
1063
|
+
if (!lendingMarket) {
|
|
1064
|
+
throw Error(`Could not fetch lending market ${reserve.state.lendingMarket.toBase58()}`);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
const marketReserves = lendingMarket.getReserves();
|
|
1068
|
+
const marketOverview: MarketOverview = {
|
|
1069
|
+
address: reserve.state.lendingMarket,
|
|
1070
|
+
reservesAsCollateral: [],
|
|
1071
|
+
minLTVPct: new Decimal(0),
|
|
1072
|
+
maxLTVPct: new Decimal(100),
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
marketReserves
|
|
1076
|
+
.filter((marketReserve) => {
|
|
1077
|
+
return (
|
|
1078
|
+
marketReserve.state.config.liquidationThresholdPct > 0 && !marketReserve.address.equals(reserve.address)
|
|
1079
|
+
);
|
|
1080
|
+
})
|
|
1081
|
+
.map((filteredReserve) => {
|
|
1082
|
+
const reserveAsCollateral: ReserveAsCollateral = {
|
|
1083
|
+
mint: filteredReserve.getLiquidityMint(),
|
|
1084
|
+
liquidationLTVPct: new Decimal(filteredReserve.state.config.liquidationThresholdPct),
|
|
1085
|
+
};
|
|
1086
|
+
marketOverview.reservesAsCollateral.push(reserveAsCollateral);
|
|
1087
|
+
if (reserveAsCollateral.liquidationLTVPct.lt(marketOverview.minLTVPct) || marketOverview.minLTVPct.eq(0)) {
|
|
1088
|
+
marketOverview.minLTVPct = reserveAsCollateral.liquidationLTVPct;
|
|
1089
|
+
}
|
|
1090
|
+
if (reserveAsCollateral.liquidationLTVPct.gt(marketOverview.maxLTVPct) || marketOverview.maxLTVPct.eq(0)) {
|
|
1091
|
+
marketOverview.maxLTVPct = reserveAsCollateral.liquidationLTVPct;
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
vaultCollateralsPerReserve.set(reserve.address, marketOverview);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
return vaultCollateralsPerReserve;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1050
1101
|
/**
|
|
1051
1102
|
* 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
|
|
1052
1103
|
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
@@ -1338,3 +1389,15 @@ export type ReserveOverview = {
|
|
|
1338
1389
|
liquidationThresholdPct: Decimal;
|
|
1339
1390
|
borrowedAmount: Decimal;
|
|
1340
1391
|
};
|
|
1392
|
+
|
|
1393
|
+
export type MarketOverview = {
|
|
1394
|
+
address: PublicKey;
|
|
1395
|
+
reservesAsCollateral: ReserveAsCollateral[]; // this MarketOverview has the reserve the caller calls for as the debt reserve and all the others as collateral reserves, so the debt reserve is not included here
|
|
1396
|
+
minLTVPct: Decimal;
|
|
1397
|
+
maxLTVPct: Decimal;
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1400
|
+
export type ReserveAsCollateral = {
|
|
1401
|
+
mint: PublicKey;
|
|
1402
|
+
liquidationLTVPct: Decimal;
|
|
1403
|
+
};
|
|
@@ -532,6 +532,78 @@ async function main() {
|
|
|
532
532
|
mode === 'execute' && console.log('User withdraw:', depositSig);
|
|
533
533
|
});
|
|
534
534
|
|
|
535
|
+
commands
|
|
536
|
+
.command('invest-all-reserves')
|
|
537
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
538
|
+
.requiredOption(
|
|
539
|
+
`--mode <string>`,
|
|
540
|
+
'simulate - to print txn simulation, inspect - to get txn simulation in explorer, execute - execute txn, multisig - to get bs58 txn for multisig usage'
|
|
541
|
+
)
|
|
542
|
+
.option(`--staging`, 'If true, will use the staging programs')
|
|
543
|
+
.option(`--multisig <string>`, 'If using multisig mode this is required, otherwise will be ignored')
|
|
544
|
+
.action(async ({ vault, mode, staging, multisig }) => {
|
|
545
|
+
const env = initializeClient(mode === 'multisig', staging);
|
|
546
|
+
const vaultAddress = new PublicKey(vault);
|
|
547
|
+
|
|
548
|
+
if (mode === 'multisig' && !multisig) {
|
|
549
|
+
throw new Error('If using multisig mode, multisig is required');
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
553
|
+
|
|
554
|
+
const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
555
|
+
const instructions = await kaminoManager.investAllReserves(env.payer.publicKey, kaminoVault);
|
|
556
|
+
|
|
557
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
558
|
+
const txInstructions: TransactionInstruction[] = [];
|
|
559
|
+
txInstructions.push(instructions[i]);
|
|
560
|
+
const investReserveSig = await processTxn(env.client, env.payer, txInstructions, mode, 2500, [], 400000);
|
|
561
|
+
|
|
562
|
+
mode === 'execute' && console.log('Reserve invested:', investReserveSig);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
commands
|
|
567
|
+
.command('invest-single-reserve')
|
|
568
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
569
|
+
.requiredOption('--reserve <string>', 'Reserve address')
|
|
570
|
+
.requiredOption(
|
|
571
|
+
`--mode <string>`,
|
|
572
|
+
'simulate - to print txn simulation, inspect - to get txn simulation in explorer, execute - execute txn, multisig - to get bs58 txn for multisig usage'
|
|
573
|
+
)
|
|
574
|
+
.option(`--staging`, 'If true, will use the staging programs')
|
|
575
|
+
.option(`--multisig <string>`, 'If using multisig mode this is required, otherwise will be ignored')
|
|
576
|
+
.action(async ({ vault, reserve, mode, staging, multisig }) => {
|
|
577
|
+
const env = initializeClient(mode === 'multisig', staging);
|
|
578
|
+
const vaultAddress = new PublicKey(vault);
|
|
579
|
+
|
|
580
|
+
if (mode === 'multisig' && !multisig) {
|
|
581
|
+
throw new Error('If using multisig mode, multisig is required');
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
585
|
+
|
|
586
|
+
const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
587
|
+
const reserveState = await Reserve.fetch(env.connection, new PublicKey(reserve), env.kLendProgramId);
|
|
588
|
+
if (!reserveState) {
|
|
589
|
+
throw new Error('Reserve not found');
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const reserveWithAddress: ReserveWithAddress = {
|
|
593
|
+
address: new PublicKey(reserve),
|
|
594
|
+
state: reserveState,
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
const instructions = await kaminoManager.investSingleReserve(
|
|
598
|
+
env.payer.publicKey,
|
|
599
|
+
kaminoVault,
|
|
600
|
+
reserveWithAddress
|
|
601
|
+
);
|
|
602
|
+
const investReserveSig = await processTxn(env.client, env.payer, instructions, mode, 2500, [], 400_000);
|
|
603
|
+
|
|
604
|
+
mode === 'execute' && console.log('Reserve invested:', investReserveSig);
|
|
605
|
+
});
|
|
606
|
+
|
|
535
607
|
// commands
|
|
536
608
|
// .command('close-vault')
|
|
537
609
|
// .requiredOption('--vault <string>', 'Vault address')
|
|
@@ -549,6 +621,59 @@ async function main() {
|
|
|
549
621
|
// console.log('Vault closed:', closeVaultSig);
|
|
550
622
|
// });
|
|
551
623
|
|
|
624
|
+
commands
|
|
625
|
+
.command('get-vault-colls')
|
|
626
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
627
|
+
.action(async ({ vault }) => {
|
|
628
|
+
const env = initializeClient(false, false);
|
|
629
|
+
|
|
630
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
631
|
+
|
|
632
|
+
const vaultAddress = new PublicKey(vault);
|
|
633
|
+
const vaultState = await new KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
634
|
+
const vaultCollaterals = await kaminoManager.getVaultCollaterals(
|
|
635
|
+
vaultState,
|
|
636
|
+
await env.connection.getSlot('confirmed')
|
|
637
|
+
);
|
|
638
|
+
vaultCollaterals.forEach((collateral) => {
|
|
639
|
+
console.log('reserve ', collateral.address);
|
|
640
|
+
console.log('market overview', collateral.reservesAsCollateral);
|
|
641
|
+
console.log('min LTV', collateral.minLTVPct);
|
|
642
|
+
console.log('max LTV', collateral.maxLTVPct);
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
commands
|
|
647
|
+
.command('get-user-shares-for-vault')
|
|
648
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
649
|
+
.requiredOption('--wallet <string>', 'User wailt address')
|
|
650
|
+
.action(async ({ vault, wallet }) => {
|
|
651
|
+
const env = initializeClient(false, false);
|
|
652
|
+
|
|
653
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
654
|
+
|
|
655
|
+
const vaultAddress = new PublicKey(vault);
|
|
656
|
+
const walletAddress = new PublicKey(wallet);
|
|
657
|
+
const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
|
|
658
|
+
const userShares = await kaminoManager.getUserSharesBalanceSingleVault(walletAddress, kaminoVault);
|
|
659
|
+
console.log(`User shares for vault ${vaultAddress.toBase58()}: ${userShares}`);
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
commands
|
|
663
|
+
.command('get-user-shares-all-vaults')
|
|
664
|
+
.requiredOption('--wallet <string>', 'User wailt address')
|
|
665
|
+
.action(async ({ wallet }) => {
|
|
666
|
+
const env = initializeClient(false, false);
|
|
667
|
+
|
|
668
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
669
|
+
|
|
670
|
+
const walletAddress = new PublicKey(wallet);
|
|
671
|
+
const userShares = await kaminoManager.getUserSharesBalanceAllVaults(walletAddress);
|
|
672
|
+
userShares.forEach((userShares, vaultAddress) => {
|
|
673
|
+
console.log(`User shares for vault ${vaultAddress}: ${userShares}`);
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
|
|
552
677
|
commands.command('get-oracle-mappings').action(async () => {
|
|
553
678
|
const env = initializeClient(false, false);
|
|
554
679
|
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
@@ -851,7 +976,11 @@ async function processTxn(
|
|
|
851
976
|
const simulation = await web3Client.sendConnection.simulateTransaction(
|
|
852
977
|
new VersionedTransaction(tx.compileMessage())
|
|
853
978
|
);
|
|
854
|
-
|
|
979
|
+
if (simulation.value.logs && simulation.value.logs.length > 0) {
|
|
980
|
+
console.log('Simulation: \n' + simulation.value.logs);
|
|
981
|
+
} else {
|
|
982
|
+
console.log('Simulation failed: \n' + simulation);
|
|
983
|
+
}
|
|
855
984
|
} else if (mode === 'inspect') {
|
|
856
985
|
console.log(
|
|
857
986
|
'Tx in B64',
|