@kamino-finance/klend-sdk 7.0.6 → 7.0.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/action.d.ts +1 -1
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +15 -15
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts +8 -0
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +10 -0
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/obligation.js +7 -6
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/vault.d.ts +8 -0
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +90 -1
- package/dist/classes/vault.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 +6 -6
- 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 +175 -149
- 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/manager/client_kamino_manager.js +15 -2
- package/dist/manager/client_kamino_manager.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/action.ts +15 -15
- package/src/classes/manager.ts +24 -1
- package/src/classes/obligation.ts +9 -9
- package/src/classes/vault.ts +100 -1
- package/src/lending_operations/repay_with_collateral_operations.ts +78 -74
- package/src/lending_operations/swap_collateral_operations.ts +15 -13
- package/src/leverage/operations.ts +350 -318
- package/src/leverage/types.ts +1 -0
- package/src/manager/client_kamino_manager.ts +19 -2
package/src/classes/action.ts
CHANGED
|
@@ -330,7 +330,7 @@ export class KaminoAction {
|
|
|
330
330
|
);
|
|
331
331
|
|
|
332
332
|
if (extraComputeBudget > 0) {
|
|
333
|
-
axn.
|
|
333
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
await axn.addRefreshObligation(payer);
|
|
@@ -363,7 +363,7 @@ export class KaminoAction {
|
|
|
363
363
|
);
|
|
364
364
|
|
|
365
365
|
if (extraComputeBudget > 0) {
|
|
366
|
-
axn.
|
|
366
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
await axn.addRefreshObligation(owner);
|
|
@@ -404,7 +404,7 @@ export class KaminoAction {
|
|
|
404
404
|
const addInitObligationForFarm = true;
|
|
405
405
|
|
|
406
406
|
if (extraComputeBudget > 0) {
|
|
407
|
-
axn.
|
|
407
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
await axn.addSupportIxs(
|
|
@@ -467,7 +467,7 @@ export class KaminoAction {
|
|
|
467
467
|
);
|
|
468
468
|
const addInitObligationForFarm = true;
|
|
469
469
|
if (extraComputeBudget > 0) {
|
|
470
|
-
axn.
|
|
470
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
471
471
|
}
|
|
472
472
|
|
|
473
473
|
if (isSome(axn.referrer)) {
|
|
@@ -529,7 +529,7 @@ export class KaminoAction {
|
|
|
529
529
|
const addInitObligationForFarm = true;
|
|
530
530
|
|
|
531
531
|
if (extraComputeBudget > 0) {
|
|
532
|
-
axn.
|
|
532
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
533
533
|
}
|
|
534
534
|
|
|
535
535
|
await axn.addSupportIxs(
|
|
@@ -572,7 +572,7 @@ export class KaminoAction {
|
|
|
572
572
|
const addInitObligationForFarm = true;
|
|
573
573
|
|
|
574
574
|
if (extraComputeBudget > 0) {
|
|
575
|
-
axn.
|
|
575
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
576
576
|
}
|
|
577
577
|
|
|
578
578
|
await axn.addSupportIxs(
|
|
@@ -620,7 +620,7 @@ export class KaminoAction {
|
|
|
620
620
|
const addInitObligationForFarm = true;
|
|
621
621
|
|
|
622
622
|
if (extraComputeBudget > 0) {
|
|
623
|
-
axn.
|
|
623
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
624
624
|
}
|
|
625
625
|
|
|
626
626
|
await axn.addSupportIxs(
|
|
@@ -679,7 +679,7 @@ export class KaminoAction {
|
|
|
679
679
|
const twoTokenAction = true;
|
|
680
680
|
|
|
681
681
|
if (extraComputeBudget > 0) {
|
|
682
|
-
axn.
|
|
682
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
683
683
|
}
|
|
684
684
|
|
|
685
685
|
if (isSome(axn.referrer)) {
|
|
@@ -776,7 +776,7 @@ export class KaminoAction {
|
|
|
776
776
|
const addInitObligationForFarm = true;
|
|
777
777
|
const twoTokenAction = true;
|
|
778
778
|
if (extraComputeBudget > 0) {
|
|
779
|
-
axn.
|
|
779
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
780
780
|
}
|
|
781
781
|
|
|
782
782
|
await axn.addSupportIxs(
|
|
@@ -830,7 +830,7 @@ export class KaminoAction {
|
|
|
830
830
|
const addInitObligationForFarm = true;
|
|
831
831
|
const twoTokenAction = true;
|
|
832
832
|
if (extraComputeBudget > 0) {
|
|
833
|
-
axn.
|
|
833
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
834
834
|
}
|
|
835
835
|
|
|
836
836
|
await axn.addSupportIxs(
|
|
@@ -886,7 +886,7 @@ export class KaminoAction {
|
|
|
886
886
|
const addInitObligationForFarmForWithdraw = false;
|
|
887
887
|
const twoTokenAction = true;
|
|
888
888
|
if (extraComputeBudget > 0) {
|
|
889
|
-
axn.
|
|
889
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
890
890
|
}
|
|
891
891
|
|
|
892
892
|
await axn.addSupportIxs(
|
|
@@ -975,7 +975,7 @@ export class KaminoAction {
|
|
|
975
975
|
const addInitObligationForFarm = true;
|
|
976
976
|
|
|
977
977
|
if (extraComputeBudget > 0) {
|
|
978
|
-
axn.
|
|
978
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
979
979
|
}
|
|
980
980
|
|
|
981
981
|
axn.depositReserves.push(...(obligationCustomizations?.addedDepositReserves || []));
|
|
@@ -1054,7 +1054,7 @@ export class KaminoAction {
|
|
|
1054
1054
|
const addInitObligationForFarm = true;
|
|
1055
1055
|
|
|
1056
1056
|
if (extraComputeBudget > 0) {
|
|
1057
|
-
axn.
|
|
1057
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
1058
1058
|
}
|
|
1059
1059
|
|
|
1060
1060
|
await axn.addSupportIxs(
|
|
@@ -1114,7 +1114,7 @@ export class KaminoAction {
|
|
|
1114
1114
|
const addInitObligationForFarm = true;
|
|
1115
1115
|
|
|
1116
1116
|
if (extraComputeBudget > 0) {
|
|
1117
|
-
axn.
|
|
1117
|
+
axn.addComputeBudgetIx(extraComputeBudget);
|
|
1118
1118
|
}
|
|
1119
1119
|
|
|
1120
1120
|
await axn.addSupportIxs(
|
|
@@ -3082,7 +3082,7 @@ export class KaminoAction {
|
|
|
3082
3082
|
this.lendingIxsLabels.push(`WithdrawReferrerFeesIx[${this.owner.toString()}]`);
|
|
3083
3083
|
}
|
|
3084
3084
|
|
|
3085
|
-
private
|
|
3085
|
+
private addComputeBudgetIx(units: number) {
|
|
3086
3086
|
this.computeBudgetIxs.push(buildComputeBudgetIx(units));
|
|
3087
3087
|
this.computeBudgetIxsLabels.push(`AddComputeBudget[${units}]`);
|
|
3088
3088
|
}
|
package/src/classes/manager.ts
CHANGED
|
@@ -1042,7 +1042,15 @@ export class KaminoManager {
|
|
|
1042
1042
|
currentSlot?: Slot,
|
|
1043
1043
|
tokensPrices?: Map<Address, Decimal>
|
|
1044
1044
|
): Promise<VaultOverview> {
|
|
1045
|
-
return this._vaultClient.getVaultOverview(
|
|
1045
|
+
return this._vaultClient.getVaultOverview(
|
|
1046
|
+
vault,
|
|
1047
|
+
price,
|
|
1048
|
+
slot,
|
|
1049
|
+
vaultReserves,
|
|
1050
|
+
kaminoMarkets,
|
|
1051
|
+
currentSlot,
|
|
1052
|
+
tokensPrices
|
|
1053
|
+
);
|
|
1046
1054
|
}
|
|
1047
1055
|
|
|
1048
1056
|
/**
|
|
@@ -1205,6 +1213,21 @@ export class KaminoManager {
|
|
|
1205
1213
|
return this._vaultClient.getVaultRewardsAPY(vault, vaultTokenPrice, farmsClient, slot);
|
|
1206
1214
|
}
|
|
1207
1215
|
|
|
1216
|
+
/**
|
|
1217
|
+
* Get all the token mints of the vault, vault farm rewards and the allocation rewards
|
|
1218
|
+
* @param vaults - the vaults to get the token mints for
|
|
1219
|
+
* @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
1220
|
+
* @param farmsMap - the farms map to get the farms for
|
|
1221
|
+
* @returns a set of token mints
|
|
1222
|
+
*/
|
|
1223
|
+
async getAllVaultsTokenMintsIncludingRewards(
|
|
1224
|
+
vaults: KaminoVault[],
|
|
1225
|
+
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
1226
|
+
farmsMap?: Map<Address, FarmState>
|
|
1227
|
+
) {
|
|
1228
|
+
return this._vaultClient.getAllVaultsTokenMintsIncludingRewards(vaults, vaultReservesMap, farmsMap);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1208
1231
|
/**
|
|
1209
1232
|
* This will return the APY of the reserve farms (debt and supply)
|
|
1210
1233
|
* @param reserve - the reserve to get the farms APY for
|
|
@@ -1399,6 +1399,13 @@ export class KaminoObligation {
|
|
|
1399
1399
|
throw new Error('Reserve not found');
|
|
1400
1400
|
}
|
|
1401
1401
|
|
|
1402
|
+
const reserveAvailableLiquidity = depositReserve.getLiquidityAvailableAmount();
|
|
1403
|
+
const withdrawalCapRemained = depositReserve
|
|
1404
|
+
.getDepositWithdrawalCapCapacity()
|
|
1405
|
+
.sub(depositReserve.getDepositWithdrawalCapCurrent(slot));
|
|
1406
|
+
|
|
1407
|
+
const reserveWithdrawalLimit = Decimal.min(withdrawalCapRemained, reserveAvailableLiquidity);
|
|
1408
|
+
|
|
1402
1409
|
const userDepositPosition = this.getDepositByReserve(depositReserve.address);
|
|
1403
1410
|
|
|
1404
1411
|
if (!userDepositPosition) {
|
|
@@ -1408,7 +1415,7 @@ export class KaminoObligation {
|
|
|
1408
1415
|
const userDepositPositionAmount = userDepositPosition.amount;
|
|
1409
1416
|
|
|
1410
1417
|
if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.equals(new Decimal(0))) {
|
|
1411
|
-
return
|
|
1418
|
+
return Decimal.max(0, Decimal.min(userDepositPositionAmount, reserveWithdrawalLimit));
|
|
1412
1419
|
}
|
|
1413
1420
|
|
|
1414
1421
|
const { maxLtv: reserveMaxLtv } = KaminoObligation.getLtvForReserve(
|
|
@@ -1436,15 +1443,8 @@ export class KaminoObligation {
|
|
|
1436
1443
|
const maxWithdrawAmount = maxWithdrawValue
|
|
1437
1444
|
.div(depositReserve.getOracleMarketPrice())
|
|
1438
1445
|
.mul(depositReserve.getMintFactor());
|
|
1439
|
-
const reserveAvailableLiquidity = depositReserve.getLiquidityAvailableAmount();
|
|
1440
1446
|
|
|
1441
|
-
|
|
1442
|
-
.getDepositWithdrawalCapCapacity()
|
|
1443
|
-
.sub(depositReserve.getDepositWithdrawalCapCurrent(slot));
|
|
1444
|
-
return Decimal.max(
|
|
1445
|
-
0,
|
|
1446
|
-
Decimal.min(userDepositPositionAmount, maxWithdrawAmount, reserveAvailableLiquidity, withdrawalCapRemained)
|
|
1447
|
-
);
|
|
1447
|
+
return Decimal.max(0, Decimal.min(userDepositPositionAmount, maxWithdrawAmount, reserveWithdrawalLimit));
|
|
1448
1448
|
}
|
|
1449
1449
|
|
|
1450
1450
|
getObligationLiquidityByReserve(reserveAddress: Address): ObligationLiquidity {
|
package/src/classes/vault.ts
CHANGED
|
@@ -1545,7 +1545,6 @@ export class KaminoVaultClient {
|
|
|
1545
1545
|
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
1546
1546
|
createAtaIfNeeded: boolean = true
|
|
1547
1547
|
): Promise<IInstruction[]> {
|
|
1548
|
-
console.log('create invest ix for reserve', reserve.address);
|
|
1549
1548
|
const vaultState = await vault.getState(this.getConnection());
|
|
1550
1549
|
const cTokenVault = await getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId);
|
|
1551
1550
|
const [lendingMarketAuth] = await lendingMarketAuthPda(reserve.state.lendingMarket, this._kaminoLendProgramId);
|
|
@@ -3082,6 +3081,106 @@ export class KaminoVaultClient {
|
|
|
3082
3081
|
return getFarmIncentives(kFarmsClient, vaultState.vaultFarm, sharePrice, stakedTokenMintDecimals, tokensPrices);
|
|
3083
3082
|
}
|
|
3084
3083
|
|
|
3084
|
+
/**
|
|
3085
|
+
* Get all the token mints of the vault, vault farm rewards and the allocation rewards
|
|
3086
|
+
* @param vaults - the vaults to get the token mints for
|
|
3087
|
+
* @param [vaultReservesMap] - the vault reserves map to get the reserves for; if not provided, the function will fetch the reserves
|
|
3088
|
+
* @param farmsMap - the farms map to get the farms for
|
|
3089
|
+
* @returns a set of token mints
|
|
3090
|
+
*/
|
|
3091
|
+
async getAllVaultsTokenMintsIncludingRewards(
|
|
3092
|
+
vaults: KaminoVault[],
|
|
3093
|
+
vaultReservesMap?: Map<Address, KaminoReserve>,
|
|
3094
|
+
farmsMap?: Map<Address, FarmState>
|
|
3095
|
+
) {
|
|
3096
|
+
const vaultsTokenMints = new Set<Address>();
|
|
3097
|
+
|
|
3098
|
+
const kFarmsMap = farmsMap ? farmsMap : new Map<Address, FarmState>();
|
|
3099
|
+
|
|
3100
|
+
const farmsToFetch = new Set<Address>();
|
|
3101
|
+
const reservesToFetch = new Set<Address>();
|
|
3102
|
+
|
|
3103
|
+
for (const vault of vaults) {
|
|
3104
|
+
const vaultState = await vault.getState(this.getConnection());
|
|
3105
|
+
vaultsTokenMints.add(vaultState.tokenMint);
|
|
3106
|
+
const hasFarm = await vault.hasFarm(this.getConnection());
|
|
3107
|
+
if (hasFarm) {
|
|
3108
|
+
const farmAddress = vaultState.vaultFarm;
|
|
3109
|
+
if (!kFarmsMap.has(farmAddress)) {
|
|
3110
|
+
farmsToFetch.add(farmAddress);
|
|
3111
|
+
} else {
|
|
3112
|
+
const farmState = kFarmsMap.get(farmAddress)!;
|
|
3113
|
+
farmState.rewardInfos.forEach((rewardInfo) => {
|
|
3114
|
+
if (rewardInfo.token.mint !== DEFAULT_PUBLIC_KEY) {
|
|
3115
|
+
vaultsTokenMints.add(rewardInfo.token.mint);
|
|
3116
|
+
}
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
const reserves = vaultState.vaultAllocationStrategy.map((allocationStrategy) => allocationStrategy.reserve);
|
|
3122
|
+
reserves.forEach((reserve) => {
|
|
3123
|
+
if (reserve === DEFAULT_PUBLIC_KEY) {
|
|
3124
|
+
return;
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
if (vaultReservesMap && !vaultReservesMap.has(reserve)) {
|
|
3128
|
+
const reserveState = vaultReservesMap.get(reserve)!;
|
|
3129
|
+
const supplyFarm = reserveState.state.farmCollateral;
|
|
3130
|
+
if (supplyFarm !== DEFAULT_PUBLIC_KEY) {
|
|
3131
|
+
if (!kFarmsMap.has(supplyFarm)) {
|
|
3132
|
+
farmsToFetch.add(supplyFarm);
|
|
3133
|
+
} else {
|
|
3134
|
+
const farmState = kFarmsMap.get(supplyFarm)!;
|
|
3135
|
+
farmState.rewardInfos.forEach((rewardInfo) => {
|
|
3136
|
+
if (rewardInfo.token.mint !== DEFAULT_PUBLIC_KEY) {
|
|
3137
|
+
vaultsTokenMints.add(rewardInfo.token.mint);
|
|
3138
|
+
}
|
|
3139
|
+
});
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
} else {
|
|
3143
|
+
reservesToFetch.add(reserve);
|
|
3144
|
+
}
|
|
3145
|
+
});
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
// fetch the reserves first so we can add their farms to farms to be fetched, if needed
|
|
3149
|
+
const missingReservesStates = await Reserve.fetchMultiple(this.getConnection(), Array.from(reservesToFetch));
|
|
3150
|
+
|
|
3151
|
+
missingReservesStates.forEach((reserveState) => {
|
|
3152
|
+
if (reserveState) {
|
|
3153
|
+
const supplyFarm = reserveState.farmCollateral;
|
|
3154
|
+
if (supplyFarm !== DEFAULT_PUBLIC_KEY) {
|
|
3155
|
+
if (!kFarmsMap.has(supplyFarm)) {
|
|
3156
|
+
farmsToFetch.add(supplyFarm);
|
|
3157
|
+
} else {
|
|
3158
|
+
const farmState = kFarmsMap.get(supplyFarm)!;
|
|
3159
|
+
farmState.rewardInfos.forEach((rewardInfo) => {
|
|
3160
|
+
if (rewardInfo.token.mint !== DEFAULT_PUBLIC_KEY) {
|
|
3161
|
+
vaultsTokenMints.add(rewardInfo.token.mint);
|
|
3162
|
+
}
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
});
|
|
3168
|
+
|
|
3169
|
+
// fetch the missing farms
|
|
3170
|
+
const missingFarmsStates = await FarmState.fetchMultiple(this.getConnection(), Array.from(farmsToFetch));
|
|
3171
|
+
missingFarmsStates.forEach((farmState) => {
|
|
3172
|
+
if (farmState) {
|
|
3173
|
+
farmState.rewardInfos.forEach((rewardInfo) => {
|
|
3174
|
+
if (rewardInfo.token.mint !== DEFAULT_PUBLIC_KEY) {
|
|
3175
|
+
vaultsTokenMints.add(rewardInfo.token.mint);
|
|
3176
|
+
}
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
});
|
|
3180
|
+
|
|
3181
|
+
return vaultsTokenMints;
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3085
3184
|
async getVaultReservesFarmsIncentives(
|
|
3086
3185
|
vaultOrState: KaminoVault | VaultState,
|
|
3087
3186
|
vaultTokenPrice: Decimal,
|
|
@@ -120,27 +120,31 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
|
|
|
120
120
|
const inputAmountLamports = Decimal.min(maxWithdrawableCollLamports, maxCollNeededFromOracle);
|
|
121
121
|
|
|
122
122
|
// Build the repay & withdraw collateral tx to get the number of accounts
|
|
123
|
-
const klendIxs: LeverageIxsOutput =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
123
|
+
const klendIxs: LeverageIxsOutput = (
|
|
124
|
+
await buildRepayWithCollateralIxs(
|
|
125
|
+
kaminoMarket,
|
|
126
|
+
debtReserve,
|
|
127
|
+
collReserve,
|
|
128
|
+
owner,
|
|
129
|
+
obligation,
|
|
130
|
+
referrer,
|
|
131
|
+
currentSlot,
|
|
132
|
+
budgetAndPriorityFeeIxs,
|
|
133
|
+
scopeRefreshConfig,
|
|
134
|
+
[
|
|
135
|
+
{
|
|
136
|
+
preActionIxs: [],
|
|
137
|
+
swapIxs: [],
|
|
138
|
+
lookupTables: [],
|
|
139
|
+
quote: {} as SwapQuote<QuoteResponse>,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
isClosingPosition,
|
|
143
|
+
repayAmountLamports,
|
|
144
|
+
inputAmountLamports,
|
|
145
|
+
useV2Ixs
|
|
146
|
+
)
|
|
147
|
+
)[0];
|
|
144
148
|
const uniqueKlendAccounts = uniqueAccountsWithProgramIds(klendIxs.instructions);
|
|
145
149
|
|
|
146
150
|
const swapQuoteInputs: SwapInputs = {
|
|
@@ -244,35 +248,33 @@ export async function getRepayWithCollIxs<QuoteResponse>({
|
|
|
244
248
|
|
|
245
249
|
const swapResponses = await swapper(swapInputs, initialInputs.klendAccounts, swapQuote);
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
swapInputs.inputAmountLamports,
|
|
263
|
-
useV2Ixs
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
return {
|
|
267
|
-
ixs: ixs.instructions,
|
|
268
|
-
lookupTables: swapResponse.lookupTables,
|
|
269
|
-
swapInputs,
|
|
270
|
-
flashLoanInfo: ixs.flashLoanInfo,
|
|
271
|
-
initialInputs,
|
|
272
|
-
quote: swapResponse.quote.quoteResponse,
|
|
273
|
-
};
|
|
274
|
-
})
|
|
251
|
+
const repayWithCollateralIxs = await buildRepayWithCollateralIxs(
|
|
252
|
+
kaminoMarket,
|
|
253
|
+
debtReserve,
|
|
254
|
+
collReserve,
|
|
255
|
+
owner,
|
|
256
|
+
obligation,
|
|
257
|
+
referrer,
|
|
258
|
+
currentSlot,
|
|
259
|
+
budgetAndPriorityFeeIxs,
|
|
260
|
+
scopeRefreshConfig,
|
|
261
|
+
swapResponses,
|
|
262
|
+
isClosingPosition,
|
|
263
|
+
debtRepayAmountLamports,
|
|
264
|
+
swapInputs.inputAmountLamports,
|
|
265
|
+
useV2Ixs
|
|
275
266
|
);
|
|
267
|
+
|
|
268
|
+
return repayWithCollateralIxs.map((ixs, index) => {
|
|
269
|
+
return {
|
|
270
|
+
ixs: ixs.instructions,
|
|
271
|
+
lookupTables: swapResponses[index].lookupTables,
|
|
272
|
+
swapInputs,
|
|
273
|
+
flashLoanInfo: ixs.flashLoanInfo,
|
|
274
|
+
initialInputs,
|
|
275
|
+
quote: swapResponses[index].quote.quoteResponse,
|
|
276
|
+
};
|
|
277
|
+
});
|
|
276
278
|
}
|
|
277
279
|
|
|
278
280
|
async function buildRepayWithCollateralIxs<QuoteResponse>(
|
|
@@ -285,12 +287,12 @@ async function buildRepayWithCollateralIxs<QuoteResponse>(
|
|
|
285
287
|
currentSlot: Slot,
|
|
286
288
|
budgetAndPriorityFeeIxs: IInstruction[] | undefined,
|
|
287
289
|
scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
|
|
288
|
-
|
|
290
|
+
swapQuoteIxsArray: SwapIxs<QuoteResponse>[],
|
|
289
291
|
isClosingPosition: boolean,
|
|
290
292
|
debtRepayAmountLamports: Decimal,
|
|
291
293
|
collWithdrawLamports: Decimal,
|
|
292
294
|
useV2Ixs: boolean
|
|
293
|
-
): Promise<LeverageIxsOutput> {
|
|
295
|
+
): Promise<LeverageIxsOutput[]> {
|
|
294
296
|
// 1. Create atas & budget txns
|
|
295
297
|
const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(1_400_000);
|
|
296
298
|
|
|
@@ -369,29 +371,31 @@ async function buildRepayWithCollateralIxs<QuoteResponse>(
|
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
// 4. Swap collateral to debt to repay flash loan
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
374
|
+
return swapQuoteIxsArray.map((swapQuoteIxs) => {
|
|
375
|
+
const { preActionIxs, swapIxs } = swapQuoteIxs;
|
|
376
|
+
const swapInstructions = removeBudgetIxs(swapIxs);
|
|
377
|
+
|
|
378
|
+
const ixs = [
|
|
379
|
+
...scopeRefreshIx,
|
|
380
|
+
...budgetIxs,
|
|
381
|
+
...atasAndIxs.map((x) => x.createAtaIx),
|
|
382
|
+
flashBorrowIx,
|
|
383
|
+
...preActionIxs,
|
|
384
|
+
...KaminoAction.actionToIxs(repayAndWithdrawAction),
|
|
385
|
+
...swapInstructions,
|
|
386
|
+
flashRepayIx,
|
|
387
|
+
];
|
|
388
|
+
|
|
389
|
+
const res: LeverageIxsOutput = {
|
|
390
|
+
flashLoanInfo: {
|
|
391
|
+
flashBorrowReserve: debtReserve.address,
|
|
392
|
+
flashLoanFee: debtReserve.getFlashLoanFee(),
|
|
393
|
+
},
|
|
394
|
+
instructions: ixs,
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
return res;
|
|
398
|
+
});
|
|
395
399
|
}
|
|
396
400
|
|
|
397
401
|
export const getMaxWithdrawLtvCheck = (
|
|
@@ -164,7 +164,16 @@ export async function getSwapCollIxs<QuoteResponse>(
|
|
|
164
164
|
// - To construct 1. (i.e. flash-borrow), we need to know the target collateral swap-out from 4.
|
|
165
165
|
|
|
166
166
|
// Construct the Klend's own ixs with a fake swap-out (only to learn the klend accounts used):
|
|
167
|
-
|
|
167
|
+
|
|
168
|
+
const scopeRefreshIx = await getScopeRefreshIx(
|
|
169
|
+
context.market,
|
|
170
|
+
context.sourceCollReserve,
|
|
171
|
+
context.targetCollReserve,
|
|
172
|
+
context.obligation,
|
|
173
|
+
context.scopeRefreshConfig
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const fakeKlendIxs = await getKlendIxs(args, FAKE_TARGET_COLL_SWAP_OUT_AMOUNT, context, scopeRefreshIx);
|
|
168
177
|
const klendAccounts = uniqueAccountsWithProgramIds(listIxs(fakeKlendIxs));
|
|
169
178
|
|
|
170
179
|
// Construct the external swap ixs (and learn the actual swap-out amount):
|
|
@@ -179,7 +188,7 @@ export async function getSwapCollIxs<QuoteResponse>(
|
|
|
179
188
|
checkResultingObligationValid(args, externalSwapIxs.swapOutAmount, context);
|
|
180
189
|
|
|
181
190
|
// Construct the Klend's own ixs with an actual swap-out amount:
|
|
182
|
-
const klendIxs = await getKlendIxs(args, externalSwapIxs.swapOutAmount, context);
|
|
191
|
+
const klendIxs = await getKlendIxs(args, externalSwapIxs.swapOutAmount, context, scopeRefreshIx);
|
|
183
192
|
|
|
184
193
|
return {
|
|
185
194
|
ixs: listIxs(klendIxs, externalSwapIxs.ixs),
|
|
@@ -275,21 +284,14 @@ type SwapCollKlendIxs = {
|
|
|
275
284
|
async function getKlendIxs(
|
|
276
285
|
args: SwapCollArgs,
|
|
277
286
|
targetCollSwapOutAmount: Decimal,
|
|
278
|
-
context: SwapCollContext<any
|
|
287
|
+
context: SwapCollContext<any>,
|
|
288
|
+
scopeRefreshIx: IInstruction[]
|
|
279
289
|
): Promise<SwapCollKlendIxs> {
|
|
280
290
|
const { ataCreationIxs, targetCollAta } = await getAtaCreationIxs(context);
|
|
281
291
|
const setupIxs = [...context.budgetAndPriorityFeeIxs, ...ataCreationIxs];
|
|
282
292
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
context.sourceCollReserve,
|
|
286
|
-
context.targetCollReserve,
|
|
287
|
-
context.obligation,
|
|
288
|
-
context.scopeRefreshConfig
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
if (scopeRefreshIxn) {
|
|
292
|
-
setupIxs.unshift(...scopeRefreshIxn);
|
|
293
|
+
if (scopeRefreshIx) {
|
|
294
|
+
setupIxs.unshift(...scopeRefreshIx);
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
const targetCollFlashBorrowedAmount = calculateTargetCollFlashBorrowedAmount(targetCollSwapOutAmount, context);
|