@kamino-finance/klend-sdk 6.0.5-beta.2 → 6.0.5-beta.21
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 +1 -1
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +32 -16
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts +29 -18
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +66 -49
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +12 -11
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +77 -37
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/obligation.d.ts +32 -2
- package/dist/classes/obligation.d.ts.map +1 -1
- package/dist/classes/obligation.js +150 -24
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/vault.d.ts +5 -3
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +8 -6
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +30 -22
- package/dist/client_kamino_manager.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.js +36 -32
- package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
- package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/swap_collateral_operations.js +4 -4
- package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
- package/dist/leverage/operations.d.ts +4 -3
- package/dist/leverage/operations.d.ts.map +1 -1
- package/dist/leverage/operations.js +186 -154
- package/dist/leverage/operations.js.map +1 -1
- package/dist/leverage/types.d.ts +1 -0
- package/dist/leverage/types.d.ts.map +1 -1
- package/dist/utils/managerTypes.d.ts +1 -2
- package/dist/utils/managerTypes.d.ts.map +1 -1
- package/dist/utils/managerTypes.js +9 -9
- package/dist/utils/managerTypes.js.map +1 -1
- package/dist/utils/obligations.d.ts +5 -0
- package/dist/utils/obligations.d.ts.map +1 -0
- package/dist/utils/obligations.js +53 -0
- package/dist/utils/obligations.js.map +1 -0
- package/dist/utils/oracle.d.ts +3 -3
- package/dist/utils/oracle.d.ts.map +1 -1
- package/dist/utils/oracle.js +2 -2
- package/dist/utils/oracle.js.map +1 -1
- package/dist/utils/pubkey.d.ts +1 -0
- package/dist/utils/pubkey.d.ts.map +1 -1
- package/dist/utils/pubkey.js +10 -0
- package/dist/utils/pubkey.js.map +1 -1
- package/package.json +3 -3
- package/src/classes/action.ts +32 -20
- package/src/classes/manager.ts +87 -54
- package/src/classes/market.ts +132 -52
- package/src/classes/obligation.ts +201 -36
- package/src/classes/vault.ts +17 -6
- package/src/client.ts +4 -4
- package/src/client_kamino_manager.ts +40 -35
- package/src/lending_operations/repay_with_collateral_operations.ts +76 -72
- package/src/lending_operations/swap_collateral_operations.ts +13 -11
- package/src/leverage/operations.ts +362 -328
- package/src/leverage/types.ts +1 -0
- package/src/utils/managerTypes.ts +1 -2
- package/src/utils/obligations.ts +69 -0
- package/src/utils/oracle.ts +5 -4
- package/src/utils/pubkey.ts +9 -0
|
@@ -39,6 +39,11 @@ export type Position = {
|
|
|
39
39
|
marketValueRefreshed: Decimal;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
export type PositionChange = {
|
|
43
|
+
reserveAddress: PublicKey;
|
|
44
|
+
amountChangeLamports: Decimal;
|
|
45
|
+
};
|
|
46
|
+
|
|
42
47
|
export type ObligationStats = {
|
|
43
48
|
userTotalDeposit: Decimal;
|
|
44
49
|
userTotalCollateralDeposit: Decimal;
|
|
@@ -491,19 +496,20 @@ export class KaminoObligation {
|
|
|
491
496
|
|
|
492
497
|
simulateDepositChange(
|
|
493
498
|
obligationDeposits: ObligationCollateral[],
|
|
494
|
-
|
|
495
|
-
changeReserve: PublicKey,
|
|
499
|
+
depositChange: PositionChange,
|
|
496
500
|
collateralExchangeRates: Map<PublicKey, Decimal>
|
|
497
501
|
): ObligationCollateral[] {
|
|
498
502
|
const newDeposits: ObligationCollateral[] = [];
|
|
499
|
-
const depositIndex = obligationDeposits.findIndex((deposit) =>
|
|
503
|
+
const depositIndex = obligationDeposits.findIndex((deposit) =>
|
|
504
|
+
deposit.depositReserve.equals(depositChange.reserveAddress)
|
|
505
|
+
);
|
|
500
506
|
|
|
501
507
|
// Always copy the previous deposits and modify the changeReserve one if it exists
|
|
502
508
|
for (let i = 0; i < obligationDeposits.length; i++) {
|
|
503
|
-
if (obligationDeposits[i].depositReserve.equals(
|
|
509
|
+
if (obligationDeposits[i].depositReserve.equals(depositChange.reserveAddress)) {
|
|
504
510
|
const coll: ObligationCollateralFields = { ...obligationDeposits[i] };
|
|
505
|
-
const exchangeRate = collateralExchangeRates.get(
|
|
506
|
-
const changeInCollateral = new Decimal(
|
|
511
|
+
const exchangeRate = collateralExchangeRates.get(depositChange.reserveAddress)!;
|
|
512
|
+
const changeInCollateral = new Decimal(depositChange.amountChangeLamports).mul(exchangeRate).toFixed(0);
|
|
507
513
|
const updatedDeposit = new Decimal(obligationDeposits[i].depositedAmount.toNumber()).add(changeInCollateral);
|
|
508
514
|
coll.depositedAmount = new BN(positiveOrZero(updatedDeposit).toString());
|
|
509
515
|
newDeposits.push(new ObligationCollateral(coll));
|
|
@@ -523,10 +529,10 @@ export class KaminoObligation {
|
|
|
523
529
|
}
|
|
524
530
|
|
|
525
531
|
const coll: ObligationCollateralFields = { ...obligationDeposits[firstBorrowIndexAvailable] };
|
|
526
|
-
const exchangeRate = collateralExchangeRates.get(
|
|
527
|
-
const changeInCollateral = new Decimal(
|
|
532
|
+
const exchangeRate = collateralExchangeRates.get(depositChange.reserveAddress)!;
|
|
533
|
+
const changeInCollateral = new Decimal(depositChange.amountChangeLamports).mul(exchangeRate).toFixed(0);
|
|
528
534
|
coll.depositedAmount = new BN(positiveOrZero(new Decimal(changeInCollateral)).toString());
|
|
529
|
-
coll.depositReserve =
|
|
535
|
+
coll.depositReserve = depositChange.reserveAddress;
|
|
530
536
|
|
|
531
537
|
newDeposits[firstBorrowIndexAvailable] = new ObligationCollateral(coll);
|
|
532
538
|
}
|
|
@@ -536,18 +542,21 @@ export class KaminoObligation {
|
|
|
536
542
|
|
|
537
543
|
simulateBorrowChange(
|
|
538
544
|
obligationBorrows: ObligationLiquidity[],
|
|
539
|
-
|
|
540
|
-
changeReserve: PublicKey,
|
|
545
|
+
borrowChange: PositionChange,
|
|
541
546
|
cumulativeBorrowRate: Decimal
|
|
542
547
|
): ObligationLiquidity[] {
|
|
543
548
|
const newBorrows: ObligationLiquidity[] = [];
|
|
544
|
-
const borrowIndex = obligationBorrows.findIndex((borrow) =>
|
|
549
|
+
const borrowIndex = obligationBorrows.findIndex((borrow) =>
|
|
550
|
+
borrow.borrowReserve.equals(borrowChange.reserveAddress)
|
|
551
|
+
);
|
|
545
552
|
|
|
546
553
|
// Always copy the previous borrows and modify the changeReserve one if it exists
|
|
547
554
|
for (let i = 0; i < obligationBorrows.length; i++) {
|
|
548
|
-
if (obligationBorrows[i].borrowReserve.equals(
|
|
555
|
+
if (obligationBorrows[i].borrowReserve.equals(borrowChange.reserveAddress)) {
|
|
549
556
|
const borrow: ObligationLiquidityFields = { ...obligationBorrows[borrowIndex] };
|
|
550
|
-
const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf)
|
|
557
|
+
const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf)
|
|
558
|
+
.toDecimal()
|
|
559
|
+
.add(borrowChange.amountChangeLamports);
|
|
551
560
|
const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();
|
|
552
561
|
borrow.borrowedAmountSf = newBorrowedAmountSf;
|
|
553
562
|
|
|
@@ -568,8 +577,8 @@ export class KaminoObligation {
|
|
|
568
577
|
}
|
|
569
578
|
|
|
570
579
|
const borrow: ObligationLiquidityFields = { ...obligationBorrows[firstBorrowIndexAvailable] };
|
|
571
|
-
borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(
|
|
572
|
-
borrow.borrowReserve =
|
|
580
|
+
borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(borrowChange.amountChangeLamports)).getValue();
|
|
581
|
+
borrow.borrowReserve = borrowChange.reserveAddress;
|
|
573
582
|
borrow.cumulativeBorrowRateBsf = {
|
|
574
583
|
padding: [],
|
|
575
584
|
value: [Fraction.fromDecimal(cumulativeBorrowRate).getValue(), new BN(0), new BN(0), new BN(0)],
|
|
@@ -643,8 +652,10 @@ export class KaminoObligation {
|
|
|
643
652
|
}
|
|
644
653
|
newObligationDeposits = this.simulateDepositChange(
|
|
645
654
|
this.state.deposits,
|
|
646
|
-
|
|
647
|
-
|
|
655
|
+
{
|
|
656
|
+
reserveAddress: collateralReservePk!,
|
|
657
|
+
amountChangeLamports: amountCollateral,
|
|
658
|
+
},
|
|
648
659
|
collateralExchangeRates
|
|
649
660
|
);
|
|
650
661
|
break;
|
|
@@ -656,8 +667,10 @@ export class KaminoObligation {
|
|
|
656
667
|
|
|
657
668
|
newObligationBorrows = this.simulateBorrowChange(
|
|
658
669
|
this.state.borrows,
|
|
659
|
-
|
|
660
|
-
|
|
670
|
+
{
|
|
671
|
+
reserveAddress: debtReservePk!,
|
|
672
|
+
amountChangeLamports: amountDebt,
|
|
673
|
+
},
|
|
661
674
|
debtReserveCumulativeBorrowRate!
|
|
662
675
|
);
|
|
663
676
|
break;
|
|
@@ -669,8 +682,10 @@ export class KaminoObligation {
|
|
|
669
682
|
|
|
670
683
|
newObligationBorrows = this.simulateBorrowChange(
|
|
671
684
|
this.state.borrows,
|
|
672
|
-
|
|
673
|
-
|
|
685
|
+
{
|
|
686
|
+
reserveAddress: debtReservePk!,
|
|
687
|
+
amountChangeLamports: amountDebt.neg(),
|
|
688
|
+
},
|
|
674
689
|
debtReserveCumulativeBorrowRate!
|
|
675
690
|
);
|
|
676
691
|
|
|
@@ -683,8 +698,10 @@ export class KaminoObligation {
|
|
|
683
698
|
}
|
|
684
699
|
newObligationDeposits = this.simulateDepositChange(
|
|
685
700
|
this.state.deposits,
|
|
686
|
-
|
|
687
|
-
|
|
701
|
+
{
|
|
702
|
+
reserveAddress: collateralReservePk!,
|
|
703
|
+
amountChangeLamports: amountCollateral.neg(),
|
|
704
|
+
},
|
|
688
705
|
collateralExchangeRates
|
|
689
706
|
);
|
|
690
707
|
break;
|
|
@@ -700,15 +717,19 @@ export class KaminoObligation {
|
|
|
700
717
|
}
|
|
701
718
|
newObligationDeposits = this.simulateDepositChange(
|
|
702
719
|
this.state.deposits,
|
|
703
|
-
|
|
704
|
-
|
|
720
|
+
{
|
|
721
|
+
reserveAddress: collateralReservePk!,
|
|
722
|
+
amountChangeLamports: amountCollateral,
|
|
723
|
+
},
|
|
705
724
|
collateralExchangeRates
|
|
706
725
|
);
|
|
707
726
|
|
|
708
727
|
newObligationBorrows = this.simulateBorrowChange(
|
|
709
728
|
this.state.borrows,
|
|
710
|
-
|
|
711
|
-
|
|
729
|
+
{
|
|
730
|
+
reserveAddress: debtReservePk!,
|
|
731
|
+
amountChangeLamports: amountDebt,
|
|
732
|
+
},
|
|
712
733
|
debtReserveCumulativeBorrowRate!
|
|
713
734
|
);
|
|
714
735
|
break;
|
|
@@ -724,14 +745,18 @@ export class KaminoObligation {
|
|
|
724
745
|
}
|
|
725
746
|
newObligationDeposits = this.simulateDepositChange(
|
|
726
747
|
this.state.deposits,
|
|
727
|
-
|
|
728
|
-
|
|
748
|
+
{
|
|
749
|
+
reserveAddress: collateralReservePk!,
|
|
750
|
+
amountChangeLamports: amountCollateral.neg(),
|
|
751
|
+
},
|
|
729
752
|
collateralExchangeRates
|
|
730
753
|
);
|
|
731
754
|
newObligationBorrows = this.simulateBorrowChange(
|
|
732
755
|
this.state.borrows,
|
|
733
|
-
|
|
734
|
-
|
|
756
|
+
{
|
|
757
|
+
reserveAddress: debtReservePk!,
|
|
758
|
+
amountChangeLamports: amountDebt.neg(),
|
|
759
|
+
},
|
|
735
760
|
debtReserveCumulativeBorrowRate!
|
|
736
761
|
);
|
|
737
762
|
break;
|
|
@@ -803,14 +828,18 @@ export class KaminoObligation {
|
|
|
803
828
|
let newObligationDeposits = this.state.deposits;
|
|
804
829
|
newObligationDeposits = this.simulateDepositChange(
|
|
805
830
|
newObligationDeposits,
|
|
806
|
-
|
|
807
|
-
|
|
831
|
+
{
|
|
832
|
+
reserveAddress: withdrawReserveAddress,
|
|
833
|
+
amountChangeLamports: withdrawAmountLamports.neg(),
|
|
834
|
+
},
|
|
808
835
|
collateralExchangeRates
|
|
809
836
|
);
|
|
810
837
|
newObligationDeposits = this.simulateDepositChange(
|
|
811
838
|
newObligationDeposits,
|
|
812
|
-
|
|
813
|
-
|
|
839
|
+
{
|
|
840
|
+
reserveAddress: depositReserveAddress,
|
|
841
|
+
amountChangeLamports: depositAmountLamports,
|
|
842
|
+
},
|
|
814
843
|
collateralExchangeRates
|
|
815
844
|
);
|
|
816
845
|
|
|
@@ -947,6 +976,7 @@ export class KaminoObligation {
|
|
|
947
976
|
} else {
|
|
948
977
|
exchangeRate = reserve.getCollateralExchangeRate();
|
|
949
978
|
}
|
|
979
|
+
|
|
950
980
|
const supplyAmount = new Decimal(deposit.depositedAmount.toString()).div(exchangeRate);
|
|
951
981
|
|
|
952
982
|
const depositValueUsd = supplyAmount.mul(getPx(reserve)).div(reserve.getMintFactor());
|
|
@@ -1074,6 +1104,73 @@ export class KaminoObligation {
|
|
|
1074
1104
|
return borrowLimit.div(userTotalCollateralDeposit);
|
|
1075
1105
|
}
|
|
1076
1106
|
|
|
1107
|
+
/**
|
|
1108
|
+
* Creates a new KaminoObligation with simulated position changes applied.
|
|
1109
|
+
* This allows you to model what the obligation would look like with deposits/borrows
|
|
1110
|
+
* without actually executing those transactions.
|
|
1111
|
+
*
|
|
1112
|
+
* @param market - The KaminoMarket instance
|
|
1113
|
+
* @param slot - The slot number for rate calculations
|
|
1114
|
+
* @param depositChanges - Optional array of deposit changes to apply
|
|
1115
|
+
* @param borrowChanges - Optional array of borrow changes to apply
|
|
1116
|
+
* @returns A new KaminoObligation instance with the changes applied
|
|
1117
|
+
*/
|
|
1118
|
+
withPositionChanges(
|
|
1119
|
+
market: KaminoMarket,
|
|
1120
|
+
slot: number,
|
|
1121
|
+
depositChanges?: PositionChange[],
|
|
1122
|
+
borrowChanges?: PositionChange[]
|
|
1123
|
+
): KaminoObligation {
|
|
1124
|
+
const reservesToRefresh: PublicKey[] = [];
|
|
1125
|
+
|
|
1126
|
+
if (depositChanges) {
|
|
1127
|
+
reservesToRefresh.push(...depositChanges.map((change) => change.reserveAddress));
|
|
1128
|
+
}
|
|
1129
|
+
if (borrowChanges) {
|
|
1130
|
+
reservesToRefresh.push(...borrowChanges.map((change) => change.reserveAddress));
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(
|
|
1134
|
+
market,
|
|
1135
|
+
this.state,
|
|
1136
|
+
slot,
|
|
1137
|
+
reservesToRefresh
|
|
1138
|
+
);
|
|
1139
|
+
|
|
1140
|
+
let newDeposits: ObligationCollateral[] = this.state.deposits;
|
|
1141
|
+
if (depositChanges) {
|
|
1142
|
+
for (const depositChange of depositChanges) {
|
|
1143
|
+
newDeposits = this.simulateDepositChange(newDeposits, depositChange, collateralExchangeRates);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
let newBorrows: ObligationLiquidity[] = this.state.borrows;
|
|
1148
|
+
if (borrowChanges) {
|
|
1149
|
+
for (const borrowChange of borrowChanges) {
|
|
1150
|
+
const reserve = market.getReserveByAddress(borrowChange.reserveAddress);
|
|
1151
|
+
if (!reserve) {
|
|
1152
|
+
throw new Error(`Reserve not found: ${borrowChange.reserveAddress}`);
|
|
1153
|
+
}
|
|
1154
|
+
newBorrows = this.simulateBorrowChange(newBorrows, borrowChange, reserve.getCumulativeBorrowRate());
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Create a deep copy of the obligation state and override deposits/borrows
|
|
1159
|
+
const newObligationState = new Obligation({
|
|
1160
|
+
...this.state,
|
|
1161
|
+
deposits: newDeposits,
|
|
1162
|
+
borrows: newBorrows,
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
return new KaminoObligation(
|
|
1166
|
+
market,
|
|
1167
|
+
this.obligationAddress,
|
|
1168
|
+
newObligationState,
|
|
1169
|
+
collateralExchangeRates,
|
|
1170
|
+
cumulativeBorrowRates
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1077
1174
|
/*
|
|
1078
1175
|
How much of a given token can a user borrow extra given an elevation group,
|
|
1079
1176
|
regardless of caps and liquidity or assuming infinite liquidity and infinite caps,
|
|
@@ -1196,6 +1293,36 @@ export class KaminoObligation {
|
|
|
1196
1293
|
}
|
|
1197
1294
|
}
|
|
1198
1295
|
|
|
1296
|
+
/*
|
|
1297
|
+
Same as getMaxBorrowAmountV2 but assumes a deposit is made first, calculating
|
|
1298
|
+
the new borrow power after the deposit, without overriding the obligation itself.
|
|
1299
|
+
|
|
1300
|
+
* @param market - The KaminoMarket instance.
|
|
1301
|
+
* @param liquidityMint - The liquidity mint Address.
|
|
1302
|
+
* @param slot - The slot number.
|
|
1303
|
+
* @param elevationGroup - The elevation group number (default: this.state.elevationGroup).
|
|
1304
|
+
* @returns The maximum borrow amount as a Decimal.
|
|
1305
|
+
* @throws Error if the reserve is not found.
|
|
1306
|
+
*/
|
|
1307
|
+
getMaxBorrowAmountV2WithDeposit(
|
|
1308
|
+
market: KaminoMarket,
|
|
1309
|
+
liquidityMint: PublicKey,
|
|
1310
|
+
slot: number,
|
|
1311
|
+
elevationGroup: number = this.state.elevationGroup,
|
|
1312
|
+
depositAmountLamports: Decimal,
|
|
1313
|
+
depositReserveAddress: PublicKey
|
|
1314
|
+
): Decimal {
|
|
1315
|
+
const depositChanges = [
|
|
1316
|
+
{
|
|
1317
|
+
reserveAddress: depositReserveAddress,
|
|
1318
|
+
amountChangeLamports: depositAmountLamports,
|
|
1319
|
+
},
|
|
1320
|
+
];
|
|
1321
|
+
const obligationWithDeposit = this.withPositionChanges(market, slot, depositChanges);
|
|
1322
|
+
|
|
1323
|
+
return obligationWithDeposit.getMaxBorrowAmountV2(market, liquidityMint, slot, elevationGroup);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1199
1326
|
/*
|
|
1200
1327
|
Returns true if the loan is eligible for the elevation group, including for the default one.
|
|
1201
1328
|
* @param market - The KaminoMarket object representing the market.
|
|
@@ -1447,6 +1574,44 @@ export class KaminoObligation {
|
|
|
1447
1574
|
);
|
|
1448
1575
|
}
|
|
1449
1576
|
|
|
1577
|
+
/**
|
|
1578
|
+
* Same as getMaxWithdrawAmount but assumes a repay is made first, calculating
|
|
1579
|
+
* the new withdraw power after the repay, without overriding the obligation itself.
|
|
1580
|
+
*
|
|
1581
|
+
* @param market - The KaminoMarket instance.
|
|
1582
|
+
* @param tokenMint - The liquidity mint Address.
|
|
1583
|
+
* @param slot - The slot number.
|
|
1584
|
+
* @param repayAmountLamports - The amount to repay in lamports (use U64_MAX for full repay).
|
|
1585
|
+
* @param repayReserveAddress - The reserve address of the borrow being repaid.
|
|
1586
|
+
* @returns The maximum withdraw amount as a Decimal.
|
|
1587
|
+
* @throws Error if the reserve is not found.
|
|
1588
|
+
*/
|
|
1589
|
+
getMaxWithdrawAmountWithRepay(
|
|
1590
|
+
market: KaminoMarket,
|
|
1591
|
+
tokenMint: PublicKey,
|
|
1592
|
+
slot: number,
|
|
1593
|
+
repayAmountLamports: Decimal,
|
|
1594
|
+
repayReserveAddress: PublicKey
|
|
1595
|
+
): Decimal {
|
|
1596
|
+
const repayReserve = market.getReserveByAddress(repayReserveAddress);
|
|
1597
|
+
if (!repayReserve) {
|
|
1598
|
+
throw new Error('Reserve not found');
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
const repayAmount = repayAmountLamports.equals(U64_MAX)
|
|
1602
|
+
? this.getBorrowAmountByReserve(repayReserve)
|
|
1603
|
+
: repayAmountLamports;
|
|
1604
|
+
const borrowChanges = [
|
|
1605
|
+
{
|
|
1606
|
+
reserveAddress: repayReserveAddress,
|
|
1607
|
+
amountChangeLamports: repayAmount.neg(), // as it's a repay
|
|
1608
|
+
},
|
|
1609
|
+
];
|
|
1610
|
+
const obligationWithRepay = this.withPositionChanges(market, slot, undefined, borrowChanges);
|
|
1611
|
+
|
|
1612
|
+
return obligationWithRepay.getMaxWithdrawAmount(market, tokenMint, slot);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1450
1615
|
getObligationLiquidityByReserve(reserveAddress: PublicKey): ObligationLiquidity {
|
|
1451
1616
|
const obligationLiquidity = this.state.borrows.find((borrow) => borrow.borrowReserve.equals(reserveAddress));
|
|
1452
1617
|
|
package/src/classes/vault.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
PubkeyHashMap,
|
|
29
29
|
Reserve,
|
|
30
30
|
UserState,
|
|
31
|
+
AllOracleAccounts,
|
|
31
32
|
} from '../lib';
|
|
32
33
|
import {
|
|
33
34
|
DepositAccounts,
|
|
@@ -838,7 +839,7 @@ export class KaminoVaultClient {
|
|
|
838
839
|
const [{ ata: adminTokenAta, createAtaIx }] = createAtasIdempotent(vaultState.vaultAdminAuthority, [
|
|
839
840
|
{
|
|
840
841
|
mint: vaultState.tokenMint,
|
|
841
|
-
tokenProgram:
|
|
842
|
+
tokenProgram: vaultState.tokenProgram,
|
|
842
843
|
},
|
|
843
844
|
]);
|
|
844
845
|
|
|
@@ -1635,7 +1636,7 @@ export class KaminoVaultClient {
|
|
|
1635
1636
|
baseVaultAuthority: vaultState.baseVaultAuthority,
|
|
1636
1637
|
tokenAta: adminTokenAta,
|
|
1637
1638
|
tokenMint: vaultState.tokenMint,
|
|
1638
|
-
tokenProgram:
|
|
1639
|
+
tokenProgram: vaultState.tokenProgram,
|
|
1639
1640
|
/** CPI accounts */
|
|
1640
1641
|
lendingMarket: marketAddress,
|
|
1641
1642
|
lendingMarketAuthority: lendingMarketAuth,
|
|
@@ -2324,9 +2325,13 @@ export class KaminoVaultClient {
|
|
|
2324
2325
|
/**
|
|
2325
2326
|
* This will load the onchain state for all the reserves that the vaults have allocations for, deduplicating the reserves
|
|
2326
2327
|
* @param vaults - the vault states to load reserves for
|
|
2328
|
+
* @param oracleAccounts
|
|
2327
2329
|
* @returns a hashmap from each reserve pubkey to the reserve state
|
|
2328
2330
|
*/
|
|
2329
|
-
async loadVaultsReserves(
|
|
2331
|
+
async loadVaultsReserves(
|
|
2332
|
+
vaults: VaultState[],
|
|
2333
|
+
oracleAccounts?: AllOracleAccounts
|
|
2334
|
+
): Promise<PubkeyHashMap<PublicKey, KaminoReserve>> {
|
|
2330
2335
|
const vaultReservesAddressesSet = new PublicKeySet(vaults.flatMap((vault) => this.getVaultReserves(vault)));
|
|
2331
2336
|
const vaultReservesAddresses = vaultReservesAddressesSet.toArray();
|
|
2332
2337
|
const reserveAccounts = await this.getConnection().getMultipleAccountsInfo(vaultReservesAddresses, 'processed');
|
|
@@ -2343,7 +2348,7 @@ export class KaminoVaultClient {
|
|
|
2343
2348
|
return reserveAccount;
|
|
2344
2349
|
});
|
|
2345
2350
|
|
|
2346
|
-
const reservesAndOracles = await getTokenOracleData(this.getConnection(), deserializedReserves);
|
|
2351
|
+
const reservesAndOracles = await getTokenOracleData(this.getConnection(), deserializedReserves, oracleAccounts);
|
|
2347
2352
|
|
|
2348
2353
|
const kaminoReserves = new PubkeyHashMap<PublicKey, KaminoReserve>();
|
|
2349
2354
|
|
|
@@ -2371,13 +2376,15 @@ export class KaminoVaultClient {
|
|
|
2371
2376
|
* @param [slot] - the slot for which to retrieve the vault collaterals for. Optional. If not provided the function will fetch the current slot
|
|
2372
2377
|
* @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
|
|
2373
2378
|
* @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
|
|
2379
|
+
* @param oracleAccounts
|
|
2374
2380
|
* @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
|
|
2375
2381
|
*/
|
|
2376
2382
|
async getVaultCollaterals(
|
|
2377
2383
|
vaultState: VaultState,
|
|
2378
2384
|
slot: number,
|
|
2379
2385
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
2380
|
-
kaminoMarkets?: KaminoMarket[]
|
|
2386
|
+
kaminoMarkets?: KaminoMarket[],
|
|
2387
|
+
oracleAccounts?: AllOracleAccounts
|
|
2381
2388
|
): Promise<PubkeyHashMap<PublicKey, MarketOverview>> {
|
|
2382
2389
|
const vaultReservesStateMap = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
2383
2390
|
const vaultReservesState: KaminoReserve[] = [];
|
|
@@ -2401,7 +2408,11 @@ export class KaminoVaultClient {
|
|
|
2401
2408
|
const missingReservesStates = (await Reserve.fetchMultiple(this.getConnection(), missingReserves.toArray())).filter(
|
|
2402
2409
|
(reserve) => reserve !== null
|
|
2403
2410
|
);
|
|
2404
|
-
const missingReservesAndOracles = await getTokenOracleData(
|
|
2411
|
+
const missingReservesAndOracles = await getTokenOracleData(
|
|
2412
|
+
this.getConnection(),
|
|
2413
|
+
missingReservesStates,
|
|
2414
|
+
oracleAccounts
|
|
2415
|
+
);
|
|
2405
2416
|
missingReservesAndOracles.forEach(([reserve, oracle], index) => {
|
|
2406
2417
|
const fetchedReserve = new KaminoReserve(
|
|
2407
2418
|
reserve,
|
package/src/client.ts
CHANGED
|
@@ -362,7 +362,7 @@ async function deposit(connection: Connection, wallet: Keypair, token: string, d
|
|
|
362
362
|
wallet.publicKey,
|
|
363
363
|
new VanillaObligation(STAGING_LENDING_MARKET),
|
|
364
364
|
true,
|
|
365
|
-
{ scope: new Scope('mainnet-beta', connection),
|
|
365
|
+
{ scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
|
|
366
366
|
);
|
|
367
367
|
console.log('User obligation', kaminoAction.getObligationPda().toString());
|
|
368
368
|
|
|
@@ -384,7 +384,7 @@ async function withdraw(connection: Connection, wallet: Keypair, token: string,
|
|
|
384
384
|
wallet.publicKey,
|
|
385
385
|
new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
|
|
386
386
|
true,
|
|
387
|
-
{ scope: new Scope('mainnet-beta', connection),
|
|
387
|
+
{ scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
|
|
388
388
|
);
|
|
389
389
|
console.log('User obligation', kaminoAction.getObligationPda().toString());
|
|
390
390
|
|
|
@@ -406,7 +406,7 @@ async function borrow(connection: Connection, wallet: Keypair, token: string, bo
|
|
|
406
406
|
wallet.publicKey,
|
|
407
407
|
new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
|
|
408
408
|
true,
|
|
409
|
-
{ scope: new Scope('mainnet-beta', connection),
|
|
409
|
+
{ scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
|
|
410
410
|
);
|
|
411
411
|
console.log('User obligation', kaminoAction.getObligationPda().toString());
|
|
412
412
|
|
|
@@ -428,7 +428,7 @@ async function repay(connection: Connection, wallet: Keypair, token: string, bor
|
|
|
428
428
|
wallet.publicKey,
|
|
429
429
|
new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
|
|
430
430
|
true,
|
|
431
|
-
{ scope: new Scope('mainnet-beta', connection),
|
|
431
|
+
{ scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] },
|
|
432
432
|
await connection.getSlot()
|
|
433
433
|
);
|
|
434
434
|
console.log('User obligation', kaminoAction.getObligationPda().toString());
|
|
@@ -52,18 +52,18 @@ import {
|
|
|
52
52
|
TokenInfo,
|
|
53
53
|
WithdrawalCaps,
|
|
54
54
|
} from './idl_codegen/types';
|
|
55
|
-
import { Fraction } from './classes
|
|
55
|
+
import { Fraction } from './classes';
|
|
56
56
|
import Decimal from 'decimal.js';
|
|
57
57
|
import { BN } from '@coral-xyz/anchor';
|
|
58
58
|
import { PythConfiguration, SwitchboardConfiguration } from './idl_codegen_kamino_vault/types';
|
|
59
59
|
import * as fs from 'fs';
|
|
60
|
-
import { MarketWithAddress } from './utils
|
|
60
|
+
import { MarketWithAddress } from './utils';
|
|
61
61
|
import {
|
|
62
62
|
ManagementFeeBps,
|
|
63
63
|
PendingVaultAdmin,
|
|
64
64
|
PerformanceFeeBps,
|
|
65
65
|
} from './idl_codegen_kamino_vault/types/VaultConfigField';
|
|
66
|
-
import { getAccountOwner } from './utils
|
|
66
|
+
import { getAccountOwner } from './utils';
|
|
67
67
|
import { getAssociatedTokenAddressSync } from '@solana/spl-token';
|
|
68
68
|
|
|
69
69
|
dotenv.config({
|
|
@@ -157,12 +157,12 @@ async function main() {
|
|
|
157
157
|
|
|
158
158
|
console.log('reserve: ', reserve.publicKey);
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
await processTxn(env.client, env.payer, txnIxs[0], mode, 2500, [reserve]);
|
|
161
161
|
|
|
162
162
|
const [lut, createLutIxs] = await createUpdateReserveConfigLutIxs(env, marketAddress, reserve.publicKey);
|
|
163
163
|
await processTxn(env.client, env.payer, createLutIxs, mode, 2500, []);
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000, 1000, [lut]);
|
|
166
166
|
|
|
167
167
|
mode === 'execute' &&
|
|
168
168
|
console.log(
|
|
@@ -224,7 +224,7 @@ async function main() {
|
|
|
224
224
|
updateEntireConfig
|
|
225
225
|
);
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
|
|
228
228
|
|
|
229
229
|
mode === 'execute' && console.log('Reserve Updated with config -> ', JSON.parse(JSON.stringify(reserveConfig)));
|
|
230
230
|
});
|
|
@@ -296,7 +296,7 @@ async function main() {
|
|
|
296
296
|
|
|
297
297
|
const { vault: vaultKp, initVaultIxs: instructions } = await kaminoManager.createVaultIxs(kaminoVaultConfig);
|
|
298
298
|
|
|
299
|
-
|
|
299
|
+
await processTxn(
|
|
300
300
|
env.client,
|
|
301
301
|
env.payer,
|
|
302
302
|
[...instructions.createAtaIfNeededIxs, ...instructions.initVaultIxs, instructions.createLUTIx],
|
|
@@ -305,7 +305,7 @@ async function main() {
|
|
|
305
305
|
[vaultKp]
|
|
306
306
|
);
|
|
307
307
|
await sleep(2000);
|
|
308
|
-
|
|
308
|
+
await processTxn(
|
|
309
309
|
env.client,
|
|
310
310
|
env.payer,
|
|
311
311
|
[...instructions.populateLUTIxs, ...instructions.cleanupIxs],
|
|
@@ -314,14 +314,7 @@ async function main() {
|
|
|
314
314
|
[]
|
|
315
315
|
);
|
|
316
316
|
|
|
317
|
-
|
|
318
|
-
env.client,
|
|
319
|
-
env.payer,
|
|
320
|
-
[instructions.initSharesMetadataIx],
|
|
321
|
-
mode,
|
|
322
|
-
2500,
|
|
323
|
-
[]
|
|
324
|
-
);
|
|
317
|
+
await processTxn(env.client, env.payer, [instructions.initSharesMetadataIx], mode, 2500, []);
|
|
325
318
|
mode === 'execute' && console.log('Vault created:', vaultKp.publicKey.toBase58());
|
|
326
319
|
});
|
|
327
320
|
|
|
@@ -1173,19 +1166,33 @@ async function main() {
|
|
|
1173
1166
|
}
|
|
1174
1167
|
});
|
|
1175
1168
|
|
|
1176
|
-
commands
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1169
|
+
commands
|
|
1170
|
+
.command('get-oracle-mappings')
|
|
1171
|
+
.requiredOption('--lending-market <string>', 'Lending Market Address')
|
|
1172
|
+
.action(async ({ lendingMarket }) => {
|
|
1173
|
+
const env = initializeClient(false, false);
|
|
1174
|
+
const kaminoManager = new KaminoManager(
|
|
1175
|
+
env.connection,
|
|
1176
|
+
DEFAULT_RECENT_SLOT_DURATION_MS,
|
|
1177
|
+
env.kLendProgramId,
|
|
1178
|
+
env.kVaultProgramId
|
|
1179
|
+
);
|
|
1180
|
+
const market = await KaminoMarket.load(
|
|
1181
|
+
env.connection,
|
|
1182
|
+
new PublicKey(lendingMarket),
|
|
1183
|
+
DEFAULT_RECENT_SLOT_DURATION_MS,
|
|
1184
|
+
env.kLendProgramId
|
|
1185
|
+
);
|
|
1186
|
+
if (!market) {
|
|
1187
|
+
throw Error(`Lending market ${lendingMarket} not found`);
|
|
1188
|
+
}
|
|
1184
1189
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1190
|
+
console.log('Getting oracle mappings');
|
|
1191
|
+
const oracleConfigs = await kaminoManager.getScopeOracleConfigs(market);
|
|
1192
|
+
for (const [oraclePrices, configs] of oracleConfigs.entries()) {
|
|
1193
|
+
console.log(`OraclePrices pubkey: ${oraclePrices.toString()}`, 'Configs:', JSON.parse(JSON.stringify(configs)));
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1189
1196
|
|
|
1190
1197
|
commands.command('get-all-vaults').action(async () => {
|
|
1191
1198
|
const env = initializeClient(false, false);
|
|
@@ -1370,7 +1377,7 @@ async function main() {
|
|
|
1370
1377
|
// executing 6 ixs in a txn to make sure they fit
|
|
1371
1378
|
for (let ixnIndex = 0; ixnIndex < ixs.length; ixnIndex += 6) {
|
|
1372
1379
|
const ixnToExecute = ixs.slice(ixnIndex, ixnIndex + 6);
|
|
1373
|
-
|
|
1380
|
+
await processTxn(env.client, env.payer, ixnToExecute, mode, 2500, [], 400_000);
|
|
1374
1381
|
}
|
|
1375
1382
|
|
|
1376
1383
|
mode === 'execute' &&
|
|
@@ -1410,7 +1417,7 @@ async function main() {
|
|
|
1410
1417
|
|
|
1411
1418
|
const ix = kaminoManager.updateLendingMarketOwnerIxs(marketWithAddress);
|
|
1412
1419
|
|
|
1413
|
-
|
|
1420
|
+
await processTxn(env.client, env.payer, [ix], mode, 2500, [], 400_000);
|
|
1414
1421
|
|
|
1415
1422
|
mode === 'execute' &&
|
|
1416
1423
|
console.log(
|
|
@@ -1465,7 +1472,7 @@ async function main() {
|
|
|
1465
1472
|
|
|
1466
1473
|
const ixs = kaminoManager.updateLendingMarketIxs(marketWithAddress, newLendingMarket);
|
|
1467
1474
|
|
|
1468
|
-
|
|
1475
|
+
await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
|
|
1469
1476
|
|
|
1470
1477
|
mode === 'execute' &&
|
|
1471
1478
|
console.log(
|
|
@@ -1520,7 +1527,7 @@ async function main() {
|
|
|
1520
1527
|
|
|
1521
1528
|
const ixs = await kaminoManager.updateReserveIxs(marketWithAddress, reserveAddress, newReserveConfig);
|
|
1522
1529
|
|
|
1523
|
-
|
|
1530
|
+
await processTxn(env.client, env.payer, ixs, mode, 2500, [], 400_000);
|
|
1524
1531
|
|
|
1525
1532
|
mode === 'execute' &&
|
|
1526
1533
|
console.log(
|
|
@@ -1811,9 +1818,7 @@ function parseBorrowRateCurve(reserveConfigFromFile: any): BorrowRateCurve {
|
|
|
1811
1818
|
|
|
1812
1819
|
curvePoints.forEach((curvePoint, index) => (finalCurvePoints[index] = curvePoint));
|
|
1813
1820
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
return borrowRateCurve;
|
|
1821
|
+
return new BorrowRateCurve({ points: finalCurvePoints });
|
|
1817
1822
|
}
|
|
1818
1823
|
|
|
1819
1824
|
function parseReserveBorrowLimitAgainstCollInEmode(reserveConfigFromFile: any): BN[] {
|