@kamino-finance/klend-sdk 7.1.7 → 7.1.9

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.
@@ -39,6 +39,11 @@ export type Position = {
39
39
  marketValueRefreshed: Decimal;
40
40
  };
41
41
 
42
+ export type PositionChange = {
43
+ reserveAddress: Address;
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
- changeInLamports: number,
495
- changeReserve: Address,
499
+ depositChange: PositionChange,
496
500
  collateralExchangeRates: Map<Address, Decimal>
497
501
  ): ObligationCollateral[] {
498
502
  const newDeposits: ObligationCollateral[] = [];
499
- const depositIndex = obligationDeposits.findIndex((deposit) => deposit.depositReserve === changeReserve);
503
+ const depositIndex = obligationDeposits.findIndex(
504
+ (deposit) => deposit.depositReserve === 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 === changeReserve) {
509
+ if (obligationDeposits[i].depositReserve === depositChange.reserveAddress) {
504
510
  const coll: ObligationCollateralFields = { ...obligationDeposits[i] };
505
- const exchangeRate = collateralExchangeRates.get(changeReserve)!;
506
- const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate).toFixed(0);
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(changeReserve)!;
527
- const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate).toFixed(0);
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 = changeReserve;
535
+ coll.depositReserve = depositChange.reserveAddress;
530
536
 
531
537
  newDeposits[firstBorrowIndexAvailable] = new ObligationCollateral(coll);
532
538
  }
@@ -536,18 +542,19 @@ export class KaminoObligation {
536
542
 
537
543
  simulateBorrowChange(
538
544
  obligationBorrows: ObligationLiquidity[],
539
- changeInLamports: number,
540
- changeReserve: Address,
545
+ borrowChange: PositionChange,
541
546
  cumulativeBorrowRate: Decimal
542
547
  ): ObligationLiquidity[] {
543
548
  const newBorrows: ObligationLiquidity[] = [];
544
- const borrowIndex = obligationBorrows.findIndex((borrow) => borrow.borrowReserve === changeReserve);
549
+ const borrowIndex = obligationBorrows.findIndex((borrow) => borrow.borrowReserve === borrowChange.reserveAddress);
545
550
 
546
551
  // Always copy the previous borrows and modify the changeReserve one if it exists
547
552
  for (let i = 0; i < obligationBorrows.length; i++) {
548
- if (obligationBorrows[i].borrowReserve === changeReserve) {
553
+ if (obligationBorrows[i].borrowReserve === borrowChange.reserveAddress) {
549
554
  const borrow: ObligationLiquidityFields = { ...obligationBorrows[borrowIndex] };
550
- const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);
555
+ const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf)
556
+ .toDecimal()
557
+ .add(borrowChange.amountChangeLamports);
551
558
  const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();
552
559
  borrow.borrowedAmountSf = newBorrowedAmountSf;
553
560
 
@@ -568,8 +575,8 @@ export class KaminoObligation {
568
575
  }
569
576
 
570
577
  const borrow: ObligationLiquidityFields = { ...obligationBorrows[firstBorrowIndexAvailable] };
571
- borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(changeInLamports)).getValue();
572
- borrow.borrowReserve = changeReserve;
578
+ borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(borrowChange.amountChangeLamports)).getValue();
579
+ borrow.borrowReserve = borrowChange.reserveAddress;
573
580
  borrow.cumulativeBorrowRateBsf = {
574
581
  padding: [],
575
582
  value: [Fraction.fromDecimal(cumulativeBorrowRate).getValue(), new BN(0), new BN(0), new BN(0)],
@@ -643,8 +650,10 @@ export class KaminoObligation {
643
650
  }
644
651
  newObligationDeposits = this.simulateDepositChange(
645
652
  this.state.deposits,
646
- amountCollateral.toNumber(),
647
- collateralReservePk!,
653
+ {
654
+ reserveAddress: collateralReservePk!,
655
+ amountChangeLamports: amountCollateral,
656
+ },
648
657
  collateralExchangeRates
649
658
  );
650
659
  break;
@@ -656,8 +665,10 @@ export class KaminoObligation {
656
665
 
657
666
  newObligationBorrows = this.simulateBorrowChange(
658
667
  this.state.borrows,
659
- amountDebt.toNumber(),
660
- debtReservePk!,
668
+ {
669
+ reserveAddress: debtReservePk!,
670
+ amountChangeLamports: amountDebt,
671
+ },
661
672
  debtReserveCumulativeBorrowRate!
662
673
  );
663
674
  break;
@@ -669,8 +680,10 @@ export class KaminoObligation {
669
680
 
670
681
  newObligationBorrows = this.simulateBorrowChange(
671
682
  this.state.borrows,
672
- amountDebt.neg().toNumber(),
673
- debtReservePk!,
683
+ {
684
+ reserveAddress: debtReservePk!,
685
+ amountChangeLamports: amountDebt.neg(),
686
+ },
674
687
  debtReserveCumulativeBorrowRate!
675
688
  );
676
689
 
@@ -683,8 +696,10 @@ export class KaminoObligation {
683
696
  }
684
697
  newObligationDeposits = this.simulateDepositChange(
685
698
  this.state.deposits,
686
- amountCollateral.neg().toNumber(),
687
- collateralReservePk!,
699
+ {
700
+ reserveAddress: collateralReservePk!,
701
+ amountChangeLamports: amountCollateral.neg(),
702
+ },
688
703
  collateralExchangeRates
689
704
  );
690
705
  break;
@@ -700,15 +715,19 @@ export class KaminoObligation {
700
715
  }
701
716
  newObligationDeposits = this.simulateDepositChange(
702
717
  this.state.deposits,
703
- amountCollateral.toNumber(),
704
- collateralReservePk!,
718
+ {
719
+ reserveAddress: collateralReservePk!,
720
+ amountChangeLamports: amountCollateral,
721
+ },
705
722
  collateralExchangeRates
706
723
  );
707
724
 
708
725
  newObligationBorrows = this.simulateBorrowChange(
709
726
  this.state.borrows,
710
- amountDebt.toNumber(),
711
- debtReservePk!,
727
+ {
728
+ reserveAddress: debtReservePk!,
729
+ amountChangeLamports: amountDebt,
730
+ },
712
731
  debtReserveCumulativeBorrowRate!
713
732
  );
714
733
  break;
@@ -724,14 +743,18 @@ export class KaminoObligation {
724
743
  }
725
744
  newObligationDeposits = this.simulateDepositChange(
726
745
  this.state.deposits,
727
- amountCollateral.neg().toNumber(),
728
- collateralReservePk!,
746
+ {
747
+ reserveAddress: collateralReservePk!,
748
+ amountChangeLamports: amountCollateral.neg(),
749
+ },
729
750
  collateralExchangeRates
730
751
  );
731
752
  newObligationBorrows = this.simulateBorrowChange(
732
753
  this.state.borrows,
733
- amountDebt.neg().toNumber(),
734
- debtReservePk!,
754
+ {
755
+ reserveAddress: debtReservePk!,
756
+ amountChangeLamports: amountDebt.neg(),
757
+ },
735
758
  debtReserveCumulativeBorrowRate!
736
759
  );
737
760
  break;
@@ -803,14 +826,18 @@ export class KaminoObligation {
803
826
  let newObligationDeposits = this.state.deposits;
804
827
  newObligationDeposits = this.simulateDepositChange(
805
828
  newObligationDeposits,
806
- withdrawAmountLamports.neg().toNumber(),
807
- withdrawReserveAddress,
829
+ {
830
+ reserveAddress: withdrawReserveAddress,
831
+ amountChangeLamports: withdrawAmountLamports.neg(),
832
+ },
808
833
  collateralExchangeRates
809
834
  );
810
835
  newObligationDeposits = this.simulateDepositChange(
811
836
  newObligationDeposits,
812
- depositAmountLamports.toNumber(),
813
- depositReserveAddress,
837
+ {
838
+ reserveAddress: depositReserveAddress,
839
+ amountChangeLamports: depositAmountLamports,
840
+ },
814
841
  collateralExchangeRates
815
842
  );
816
843
 
@@ -947,6 +974,7 @@ export class KaminoObligation {
947
974
  } else {
948
975
  exchangeRate = reserve.getCollateralExchangeRate();
949
976
  }
977
+
950
978
  const supplyAmount = new Decimal(deposit.depositedAmount.toString()).div(exchangeRate);
951
979
 
952
980
  const depositValueUsd = supplyAmount.mul(getPx(reserve)).div(reserve.getMintFactor());
@@ -1055,23 +1083,98 @@ export class KaminoObligation {
1055
1083
  };
1056
1084
  }
1057
1085
 
1058
- getMaxLoanLtvGivenElevationGroup(market: KaminoMarket, elevationGroup: number, slot: Slot): Decimal {
1086
+ getMaxLoanLtvAndLiquidationLtvGivenElevationGroup(
1087
+ market: KaminoMarket,
1088
+ elevationGroup: number,
1089
+ slot: Slot
1090
+ ): { maxLtv: Decimal; liquidationLtv: Decimal } {
1059
1091
  const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();
1060
1092
  const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
1061
1093
 
1062
- const { borrowLimit, userTotalCollateralDeposit } = KaminoObligation.calculateObligationDeposits(
1094
+ const { borrowLimit, userTotalCollateralDeposit, borrowLiquidationLimit } =
1095
+ KaminoObligation.calculateObligationDeposits(
1096
+ market,
1097
+ this.state.deposits,
1098
+ collateralExchangeRates,
1099
+ elevationGroup,
1100
+ getOraclePx
1101
+ );
1102
+
1103
+ if (userTotalCollateralDeposit.eq(0)) {
1104
+ return { maxLtv: new Decimal(0), liquidationLtv: new Decimal(0) };
1105
+ }
1106
+
1107
+ return {
1108
+ maxLtv: borrowLimit.div(userTotalCollateralDeposit),
1109
+ liquidationLtv: borrowLiquidationLimit.div(userTotalCollateralDeposit),
1110
+ };
1111
+ }
1112
+
1113
+ /**
1114
+ * Creates a new KaminoObligation with simulated position changes applied.
1115
+ * This allows you to model what the obligation would look like with deposits/borrows
1116
+ * without actually executing those transactions.
1117
+ *
1118
+ * @param market - The KaminoMarket instance
1119
+ * @param slot - The slot number for rate calculations
1120
+ * @param depositChanges - Optional array of deposit changes to apply
1121
+ * @param borrowChanges - Optional array of borrow changes to apply
1122
+ * @returns A new KaminoObligation instance with the changes applied
1123
+ */
1124
+ withPositionChanges(
1125
+ market: KaminoMarket,
1126
+ slot: Slot,
1127
+ depositChanges?: PositionChange[],
1128
+ borrowChanges?: PositionChange[]
1129
+ ): KaminoObligation {
1130
+ const reservesToRefresh: Address[] = [];
1131
+
1132
+ if (depositChanges) {
1133
+ reservesToRefresh.push(...depositChanges.map((change) => change.reserveAddress));
1134
+ }
1135
+ if (borrowChanges) {
1136
+ reservesToRefresh.push(...borrowChanges.map((change) => change.reserveAddress));
1137
+ }
1138
+
1139
+ const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(
1063
1140
  market,
1064
- this.state.deposits,
1065
- collateralExchangeRates,
1066
- elevationGroup,
1067
- getOraclePx
1141
+ this.state,
1142
+ slot,
1143
+ reservesToRefresh
1068
1144
  );
1069
1145
 
1070
- if (borrowLimit.eq(0) || userTotalCollateralDeposit.eq(0)) {
1071
- return new Decimal(0);
1146
+ let newDeposits: ObligationCollateral[] = this.state.deposits;
1147
+ if (depositChanges) {
1148
+ for (const depositChange of depositChanges) {
1149
+ newDeposits = this.simulateDepositChange(newDeposits, depositChange, collateralExchangeRates);
1150
+ }
1072
1151
  }
1073
1152
 
1074
- return borrowLimit.div(userTotalCollateralDeposit);
1153
+ let newBorrows: ObligationLiquidity[] = this.state.borrows;
1154
+ if (borrowChanges) {
1155
+ for (const borrowChange of borrowChanges) {
1156
+ const reserve = market.getReserveByAddress(borrowChange.reserveAddress);
1157
+ if (!reserve) {
1158
+ throw new Error(`Reserve not found: ${borrowChange.reserveAddress}`);
1159
+ }
1160
+ newBorrows = this.simulateBorrowChange(newBorrows, borrowChange, reserve.getCumulativeBorrowRate());
1161
+ }
1162
+ }
1163
+
1164
+ // Create a deep copy of the obligation state and override deposits/borrows
1165
+ const newObligationState = new Obligation({
1166
+ ...this.state,
1167
+ deposits: newDeposits,
1168
+ borrows: newBorrows,
1169
+ });
1170
+
1171
+ return new KaminoObligation(
1172
+ market,
1173
+ this.obligationAddress,
1174
+ newObligationState,
1175
+ collateralExchangeRates,
1176
+ cumulativeBorrowRates
1177
+ );
1075
1178
  }
1076
1179
 
1077
1180
  /*
@@ -1196,6 +1299,36 @@ export class KaminoObligation {
1196
1299
  }
1197
1300
  }
1198
1301
 
1302
+ /*
1303
+ Same as getMaxBorrowAmountV2 but assumes a deposit is made first, calculating
1304
+ the new borrow power after the deposit, without overriding the obligation itself.
1305
+
1306
+ * @param market - The KaminoMarket instance.
1307
+ * @param liquidityMint - The liquidity mint Address.
1308
+ * @param slot - The slot number.
1309
+ * @param elevationGroup - The elevation group number (default: this.state.elevationGroup).
1310
+ * @returns The maximum borrow amount as a Decimal.
1311
+ * @throws Error if the reserve is not found.
1312
+ */
1313
+ getMaxBorrowAmountV2WithDeposit(
1314
+ market: KaminoMarket,
1315
+ liquidityMint: Address,
1316
+ slot: Slot,
1317
+ elevationGroup: number = this.state.elevationGroup,
1318
+ depositAmountLamports: Decimal,
1319
+ depositReserveAddress: Address
1320
+ ): Decimal {
1321
+ const depositChanges = [
1322
+ {
1323
+ reserveAddress: depositReserveAddress,
1324
+ amountChangeLamports: depositAmountLamports,
1325
+ },
1326
+ ];
1327
+ const obligationWithDeposit = this.withPositionChanges(market, slot, depositChanges);
1328
+
1329
+ return obligationWithDeposit.getMaxBorrowAmountV2(market, liquidityMint, slot, elevationGroup);
1330
+ }
1331
+
1199
1332
  /*
1200
1333
  Returns true if the loan is eligible for the elevation group, including for the default one.
1201
1334
  * @param market - The KaminoMarket object representing the market.
@@ -1447,6 +1580,44 @@ export class KaminoObligation {
1447
1580
  return Decimal.max(0, Decimal.min(userDepositPositionAmount, maxWithdrawAmount, reserveWithdrawalLimit));
1448
1581
  }
1449
1582
 
1583
+ /**
1584
+ * Same as getMaxWithdrawAmount but assumes a repay is made first, calculating
1585
+ * the new withdraw power after the repay, without overriding the obligation itself.
1586
+ *
1587
+ * @param market - The KaminoMarket instance.
1588
+ * @param tokenMint - The liquidity mint Address.
1589
+ * @param slot - The slot number.
1590
+ * @param repayAmountLamports - The amount to repay in lamports (use U64_MAX for full repay).
1591
+ * @param repayReserveAddress - The reserve address of the borrow being repaid.
1592
+ * @returns The maximum withdraw amount as a Decimal.
1593
+ * @throws Error if the reserve is not found.
1594
+ */
1595
+ getMaxWithdrawAmountWithRepay(
1596
+ market: KaminoMarket,
1597
+ tokenMint: Address,
1598
+ slot: Slot,
1599
+ repayAmountLamports: Decimal,
1600
+ repayReserveAddress: Address
1601
+ ): Decimal {
1602
+ const repayReserve = market.getReserveByAddress(repayReserveAddress);
1603
+ if (!repayReserve) {
1604
+ throw new Error('Reserve not found');
1605
+ }
1606
+
1607
+ const repayAmount = repayAmountLamports.equals(U64_MAX)
1608
+ ? this.getBorrowAmountByReserve(repayReserve)
1609
+ : repayAmountLamports;
1610
+ const borrowChanges = [
1611
+ {
1612
+ reserveAddress: repayReserveAddress,
1613
+ amountChangeLamports: repayAmount.neg(), // as it's a repay
1614
+ },
1615
+ ];
1616
+ const obligationWithRepay = this.withPositionChanges(market, slot, undefined, borrowChanges);
1617
+
1618
+ return obligationWithRepay.getMaxWithdrawAmount(market, tokenMint, slot);
1619
+ }
1620
+
1450
1621
  getObligationLiquidityByReserve(reserveAddress: Address): ObligationLiquidity {
1451
1622
  const obligationLiquidity = this.state.borrows.find((borrow) => borrow.borrowReserve === reserveAddress);
1452
1623
 
@@ -970,7 +970,7 @@ export class KaminoVaultClient {
970
970
  const [{ ata: adminTokenAta, createAtaIx }] = await createAtasIdempotent(vaultAdmin, [
971
971
  {
972
972
  mint: vaultState.tokenMint,
973
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
973
+ tokenProgram: vaultState.tokenProgram,
974
974
  },
975
975
  ]);
976
976
 
@@ -1744,7 +1744,7 @@ export class KaminoVaultClient {
1744
1744
  baseVaultAuthority: vaultState.baseVaultAuthority,
1745
1745
  tokenAta: adminTokenAta,
1746
1746
  tokenMint: vaultState.tokenMint,
1747
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
1747
+ tokenProgram: vaultState.tokenProgram,
1748
1748
  /** CPI accounts */
1749
1749
  lendingMarket: marketAddress,
1750
1750
  lendingMarketAuthority: lendingMarketAuth,
@@ -302,7 +302,7 @@ async function buildRepayWithCollateralIxs<QuoteResponse>(
302
302
 
303
303
  // 2. Flash borrow & repay the debt to repay amount needed
304
304
  const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
305
- borrowIxIndex: budgetIxs.length + atasAndIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
305
+ borrowIxIndex: atasAndIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
306
306
  userTransferAuthority: owner,
307
307
  lendingMarketAuthority: await market.getLendingMarketAuthority(),
308
308
  lendingMarketAddress: market.getAddress(),
@@ -371,13 +371,13 @@ async function buildRepayWithCollateralIxs<QuoteResponse>(
371
371
 
372
372
  const ixs = [
373
373
  ...scopeRefreshIx,
374
- ...budgetIxs,
375
374
  ...atasAndIxs.map((x) => x.createAtaIx),
376
375
  flashBorrowIx,
377
376
  ...preActionIxs,
378
377
  ...KaminoAction.actionToIxs(repayAndWithdrawAction),
379
378
  ...swapInstructions,
380
379
  flashRepayIx,
380
+ ...budgetIxs,
381
381
  ];
382
382
 
383
383
  const res: LeverageIxsOutput = {
@@ -273,7 +273,7 @@ async function getKlendIxs(
273
273
  scopeRefreshIx: Instruction[]
274
274
  ): Promise<SwapCollKlendIxs> {
275
275
  const { ataCreationIxs, targetCollAta } = await getAtaCreationIxs(context);
276
- const setupIxs = [...context.budgetAndPriorityFeeIxs, ...ataCreationIxs];
276
+ const setupIxs = [...ataCreationIxs];
277
277
 
278
278
  if (scopeRefreshIx) {
279
279
  setupIxs.unshift(...scopeRefreshIx);
@@ -294,7 +294,7 @@ async function getKlendIxs(
294
294
  context
295
295
  );
296
296
 
297
- const cleanupIxs = await getAtaCloseIxs(context);
297
+ const cleanupIxs = [...(await getAtaCloseIxs(context)), ...context.budgetAndPriorityFeeIxs];
298
298
 
299
299
  return {
300
300
  setupIxs,
@@ -324,8 +324,7 @@ async function buildDepositWithLeverageIxs<QuoteResponse>(
324
324
  // 2. Flash borrow & repay the collateral amount needed for given leverage
325
325
  // if user deposits coll, then we borrow the diff, else we borrow the entire amount
326
326
  const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
327
- borrowIxIndex:
328
- budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
327
+ borrowIxIndex: createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
329
328
  userTransferAuthority: owner,
330
329
  lendingMarketAuthority: await market.getLendingMarketAuthority(),
331
330
  lendingMarketAddress: market.getAddress(),
@@ -371,13 +370,13 @@ async function buildDepositWithLeverageIxs<QuoteResponse>(
371
370
  flashLoanInfo,
372
371
  instructions: [
373
372
  ...scopeRefreshIx,
374
- ...budgetIxs,
375
373
  ...createAtasIxs,
376
374
  ...fillWsolAtaIxs,
377
375
  ...[flashBorrowIx],
378
376
  ...KaminoAction.actionToIxs(kaminoDepositAndBorrowAction),
379
377
  ...swapInstructions,
380
378
  ...[flashRepayIx],
379
+ ...budgetIxs,
381
380
  ],
382
381
  };
383
382
  });
@@ -675,8 +674,7 @@ export async function buildWithdrawWithLeverageIxs<QuoteResponse>(
675
674
  // We borrow exactly how much we need to repay
676
675
  // and repay that + flash amount fee
677
676
  const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
678
- borrowIxIndex:
679
- budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
677
+ borrowIxIndex: createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
680
678
  userTransferAuthority: owner,
681
679
  lendingMarketAuthority: await market.getLendingMarketAuthority(),
682
680
  lendingMarketAddress: market.getAddress(),
@@ -719,7 +717,6 @@ export async function buildWithdrawWithLeverageIxs<QuoteResponse>(
719
717
  },
720
718
  instructions: [
721
719
  ...scopeRefreshIx,
722
- ...budgetIxs,
723
720
  ...createAtasIxs,
724
721
  ...fillWsolAtaIxs,
725
722
  ...[flashBorrowIx],
@@ -727,6 +724,7 @@ export async function buildWithdrawWithLeverageIxs<QuoteResponse>(
727
724
  ...swapInstructions,
728
725
  ...[flashRepayIx],
729
726
  ...closeWsolAtaIxs,
727
+ ...budgetIxs,
730
728
  ],
731
729
  };
732
730
  });
@@ -1129,7 +1127,7 @@ async function buildIncreaseLeverageIxs<QuoteResponse>(
1129
1127
 
1130
1128
  // 2. Create borrow flash loan instruction
1131
1129
  const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
1132
- borrowIxIndex: budgetIxs.length + createAtasIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0), // TODO: how about user metadata ixs
1130
+ borrowIxIndex: createAtasIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0), // TODO: how about user metadata ixs
1133
1131
  userTransferAuthority: owner,
1134
1132
  lendingMarketAuthority: await kaminoMarket.getLendingMarketAuthority(),
1135
1133
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1180,13 +1178,13 @@ async function buildIncreaseLeverageIxs<QuoteResponse>(
1180
1178
 
1181
1179
  const ixs = [
1182
1180
  ...scopeRefreshIx,
1183
- ...budgetIxs,
1184
1181
  ...createAtasIxs,
1185
1182
  ...[flashBorrowIx],
1186
1183
  ...KaminoAction.actionToIxs(depositAction),
1187
1184
  ...KaminoAction.actionToIxs(borrowAction),
1188
1185
  ...swapInstructions,
1189
1186
  ...[flashRepayIx],
1187
+ ...budgetIxs,
1190
1188
  ];
1191
1189
 
1192
1190
  const flashBorrowReserve = collReserve!;
@@ -1270,8 +1268,7 @@ async function buildDecreaseLeverageIxs<QuoteResponse>(
1270
1268
 
1271
1269
  // 3. Flash borrow & repay amount to repay (debt)
1272
1270
  const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
1273
- borrowIxIndex:
1274
- budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
1271
+ borrowIxIndex: createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
1275
1272
  userTransferAuthority: owner,
1276
1273
  lendingMarketAuthority: await kaminoMarket.getLendingMarketAuthority(),
1277
1274
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1325,7 +1322,6 @@ async function buildDecreaseLeverageIxs<QuoteResponse>(
1325
1322
 
1326
1323
  const ixs = [
1327
1324
  ...scopeRefreshIx,
1328
- ...budgetIxs,
1329
1325
  ...createAtasIxs,
1330
1326
  ...fillWsolAtaIxs,
1331
1327
  ...[flashBorrowIx],
@@ -1334,6 +1330,7 @@ async function buildDecreaseLeverageIxs<QuoteResponse>(
1334
1330
  ...swapInstructions,
1335
1331
  ...[flashRepayIx],
1336
1332
  ...closeWsolAtaIxs,
1333
+ ...budgetIxs,
1337
1334
  ];
1338
1335
 
1339
1336
  const res: LeverageIxsOutput = {