@kamino-finance/klend-sdk 4.0.1 → 4.1.0

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.
Files changed (72) hide show
  1. package/README.md +2 -2
  2. package/dist/classes/action.d.ts +3 -1
  3. package/dist/classes/action.d.ts.map +1 -1
  4. package/dist/classes/action.js +62 -61
  5. package/dist/classes/action.js.map +1 -1
  6. package/dist/classes/market.d.ts +5 -5
  7. package/dist/classes/market.d.ts.map +1 -1
  8. package/dist/classes/market.js +14 -14
  9. package/dist/classes/market.js.map +1 -1
  10. package/dist/classes/obligation.d.ts +10 -1
  11. package/dist/classes/obligation.d.ts.map +1 -1
  12. package/dist/classes/obligation.js +48 -28
  13. package/dist/classes/obligation.js.map +1 -1
  14. package/dist/classes/reserve.d.ts +3 -1
  15. package/dist/classes/reserve.d.ts.map +1 -1
  16. package/dist/classes/reserve.js +39 -5
  17. package/dist/classes/reserve.js.map +1 -1
  18. package/dist/classes/shared.d.ts +8 -0
  19. package/dist/classes/shared.d.ts.map +1 -1
  20. package/dist/classes/shared.js +6 -1
  21. package/dist/classes/shared.js.map +1 -1
  22. package/dist/classes/vault.d.ts.map +1 -1
  23. package/dist/classes/vault.js +19 -5
  24. package/dist/classes/vault.js.map +1 -1
  25. package/dist/lending_operations/repay_with_collateral_calcs.d.ts +18 -1
  26. package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
  27. package/dist/lending_operations/repay_with_collateral_calcs.js +62 -0
  28. package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
  29. package/dist/lending_operations/repay_with_collateral_operations.d.ts +27 -43
  30. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  31. package/dist/lending_operations/repay_with_collateral_operations.js +99 -152
  32. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  33. package/dist/leverage/operations.d.ts +14 -3
  34. package/dist/leverage/operations.d.ts.map +1 -1
  35. package/dist/leverage/operations.js +184 -128
  36. package/dist/leverage/operations.js.map +1 -1
  37. package/dist/utils/ata.d.ts +12 -3
  38. package/dist/utils/ata.d.ts.map +1 -1
  39. package/dist/utils/ata.js +26 -39
  40. package/dist/utils/ata.js.map +1 -1
  41. package/dist/utils/index.d.ts +0 -2
  42. package/dist/utils/index.d.ts.map +1 -1
  43. package/dist/utils/index.js +0 -2
  44. package/dist/utils/index.js.map +1 -1
  45. package/dist/utils/instruction.d.ts +1 -0
  46. package/dist/utils/instruction.d.ts.map +1 -1
  47. package/dist/utils/instruction.js +18 -0
  48. package/dist/utils/instruction.js.map +1 -1
  49. package/package.json +3 -3
  50. package/src/classes/action.ts +92 -98
  51. package/src/classes/market.ts +19 -20
  52. package/src/classes/obligation.ts +80 -38
  53. package/src/classes/reserve.ts +56 -8
  54. package/src/classes/shared.ts +10 -0
  55. package/src/classes/vault.ts +23 -19
  56. package/src/lending_operations/repay_with_collateral_calcs.ts +98 -1
  57. package/src/lending_operations/repay_with_collateral_operations.ts +233 -253
  58. package/src/leverage/operations.ts +227 -140
  59. package/src/utils/ata.ts +33 -56
  60. package/src/utils/index.ts +0 -2
  61. package/src/utils/instruction.ts +22 -0
  62. package/dist/utils/layout.d.ts +0 -14
  63. package/dist/utils/layout.d.ts.map +0 -1
  64. package/dist/utils/layout.js +0 -123
  65. package/dist/utils/layout.js.map +0 -1
  66. package/dist/utils/syncNative.d.ts +0 -11
  67. package/dist/utils/syncNative.d.ts.map +0 -1
  68. package/dist/utils/syncNative.js +0 -45
  69. package/dist/utils/syncNative.js.map +0 -1
  70. package/src/global.d.ts +0 -1
  71. package/src/utils/layout.ts +0 -118
  72. package/src/utils/syncNative.ts +0 -22
@@ -1,224 +1,276 @@
1
1
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
2
- import { KaminoAction, KaminoMarket, KaminoObligation, numberToLamportsDecimal } from '../classes';
3
- import { SwapInputs, SwapIxnsProvider, getFlashLoanInstructions, toJson } from '../leverage';
2
+ import { KaminoAction, KaminoMarket, KaminoObligation, KaminoReserve } from '../classes';
4
3
  import {
5
- PublicKeySet,
6
- ScopeRefresh,
7
- U64_MAX,
8
- getAtasWithCreateIxnsIfMissing,
4
+ getFlashLoanInstructions,
5
+ SwapInputs,
6
+ SwapQuote,
7
+ SwapQuoteIxs,
8
+ SwapQuoteIxsProvider,
9
+ SwapQuoteProvider,
10
+ } from '../leverage';
11
+ import {
12
+ createAtasIdempotent,
9
13
  getComputeBudgetAndPriorityFeeIxns,
10
14
  removeBudgetAndAtaIxns,
15
+ ScopeRefresh,
16
+ U64_MAX,
17
+ uniqueAccounts,
11
18
  } from '../utils';
12
- import { PublicKey, TransactionInstruction } from '@solana/web3.js';
19
+ import { AddressLookupTableAccount, PublicKey, TransactionInstruction } from '@solana/web3.js';
13
20
  import Decimal from 'decimal.js';
21
+ import { calcMaxWithdrawCollateral, calcRepayAmountWithSlippage } from './repay_with_collateral_calcs';
14
22
 
15
- export const repayWithCollCalcs = (props: {
16
- repayAmount: Decimal;
17
- priceDebtToColl: Decimal;
18
- slippagePct: Decimal;
19
- flashLoanFeePct: Decimal;
20
- }): {
21
- repayAmount: Decimal;
22
- collToSwapIn: Decimal;
23
- swapDebtExpectedOut: Decimal;
24
- } => {
25
- // Initialize local variables from the props object
26
- const { repayAmount, priceDebtToColl, slippagePct, flashLoanFeePct } = props;
27
-
28
- const slippage = slippagePct.div('100');
29
- const flashLoanFee = flashLoanFeePct.div('100');
30
-
31
- const swapDebtExpectedOut = repayAmount.mul(new Decimal(1.0).add(flashLoanFee));
32
- const collToSwapIn = swapDebtExpectedOut.mul(new Decimal(1.0).add(slippage)).mul(priceDebtToColl);
33
-
34
- return {
35
- repayAmount,
36
- collToSwapIn,
37
- swapDebtExpectedOut,
38
- };
23
+ export type RepayWithCollIxsResponse<QuoteResponse> = {
24
+ ixs: TransactionInstruction[];
25
+ lookupTables: AddressLookupTableAccount[];
26
+ swapInputs: SwapInputs;
27
+ initialInputs: InitialInputs<QuoteResponse>;
39
28
  };
40
29
 
41
- export type InitialInputs = {
42
- repayAmount: Decimal;
43
- priceDebtToColl: Decimal;
44
- slippagePct: Decimal;
30
+ export type InitialInputs<QuoteResponse> = {
31
+ debtRepayAmountLamports: Decimal;
32
+ flashRepayAmountLamports: Decimal;
33
+ swapQuote: SwapQuote<QuoteResponse>;
45
34
  currentSlot: number;
35
+ klendAccounts: Array<PublicKey>;
46
36
  };
47
37
 
48
- export const getRepayWithCollSwapInputs = (props: {
49
- repayAmount: Decimal;
50
- priceDebtToColl: Decimal;
51
- slippagePct: Decimal;
38
+ interface RepayWithCollSwapInputsProps<QuoteResponse> {
52
39
  kaminoMarket: KaminoMarket;
53
40
  debtTokenMint: PublicKey;
54
41
  collTokenMint: PublicKey;
55
42
  obligation: KaminoObligation;
43
+ referrer: PublicKey;
56
44
  currentSlot: number;
57
- }): {
45
+ repayAmount: Decimal;
46
+ isClosingPosition: boolean;
47
+ budgetAndPriorityFeeIxs?: TransactionInstruction[];
48
+ scopeRefresh?: ScopeRefresh;
49
+ quoter: SwapQuoteProvider<QuoteResponse>;
50
+ }
51
+
52
+ export async function getRepayWithCollSwapInputs<QuoteResponse>({
53
+ collTokenMint,
54
+ currentSlot,
55
+ debtTokenMint,
56
+ kaminoMarket,
57
+ obligation,
58
+ quoter,
59
+ referrer,
60
+ repayAmount,
61
+ isClosingPosition,
62
+ budgetAndPriorityFeeIxs,
63
+ scopeRefresh,
64
+ }: RepayWithCollSwapInputsProps<QuoteResponse>): Promise<{
58
65
  swapInputs: SwapInputs;
59
- initialInputs: InitialInputs;
60
- } => {
61
- const {
66
+ initialInputs: InitialInputs<QuoteResponse>;
67
+ }> {
68
+ const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
69
+ const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
70
+ if (!collReserve) {
71
+ throw new Error(`Collateral reserve with mint ${collReserve} not found in market ${kaminoMarket.getAddress()}`);
72
+ }
73
+ if (!debtReserve) {
74
+ throw new Error(`Debt reserve with mint ${debtReserve} not found in market ${kaminoMarket.getAddress()}`);
75
+ }
76
+
77
+ const { repayAmountLamports, flashRepayAmountLamports } = calcRepayAmountWithSlippage(
78
+ kaminoMarket,
79
+ debtReserve,
80
+ currentSlot,
81
+ obligation,
62
82
  repayAmount,
63
- priceDebtToColl,
64
- slippagePct,
83
+ referrer
84
+ );
85
+
86
+ const debtPosition = obligation.getBorrowByReserve(debtReserve.address);
87
+ const collPosition = obligation.getDepositByReserve(collReserve.address);
88
+ if (!debtPosition) {
89
+ throw new Error(
90
+ `Debt position not found for ${debtReserve.stats.symbol} reserve ${debtReserve.address} in obligation ${obligation.obligationAddress}`
91
+ );
92
+ }
93
+ if (!collPosition) {
94
+ throw new Error(
95
+ `Collateral position not found for ${collReserve.stats.symbol} reserve ${collReserve.address} in obligation ${obligation.obligationAddress}`
96
+ );
97
+ }
98
+ const { withdrawableCollLamports } = calcMaxWithdrawCollateral(
65
99
  kaminoMarket,
66
- debtTokenMint,
67
- collTokenMint,
100
+ collReserve.address,
101
+ debtReserve.address,
68
102
  obligation,
69
- currentSlot,
70
- } = props;
71
- const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
72
- const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
73
- const flashLoanFeePct = debtReserve?.getFlashLoanFee().ceil() || new Decimal(0);
103
+ repayAmountLamports
104
+ );
74
105
 
75
- const irSlippageBpsForDebt = obligation!
76
- .estimateObligationInterestRate(
77
- kaminoMarket,
78
- debtReserve!,
79
- obligation?.state.borrows.find((borrow) => borrow.borrowReserve?.equals(debtReserve!.address))!,
80
- currentSlot
81
- )
82
- .toDecimalPlaces(debtReserve?.state.liquidity.mintDecimals.toNumber()!, Decimal.ROUND_CEIL);
83
- // add 0.1% to irSlippageBpsForDebt because we don't want to estimate slightly less than SC and end up not repaying enough
84
- const repayAmountIrAdjusted = repayAmount
85
- .mul(irSlippageBpsForDebt.mul(new Decimal('1.001')))
86
- .toDecimalPlaces(debtReserve?.state.liquidity.mintDecimals.toNumber()!, Decimal.ROUND_CEIL);
106
+ const swapQuoteInputs: SwapInputs = {
107
+ inputAmountLamports: withdrawableCollLamports,
108
+ inputMint: collTokenMint,
109
+ outputMint: debtTokenMint,
110
+ };
87
111
 
88
- const repayCalcs = repayWithCollCalcs({
89
- repayAmount: repayAmountIrAdjusted,
90
- priceDebtToColl,
91
- slippagePct,
92
- flashLoanFeePct: flashLoanFeePct,
93
- });
112
+ // Build the repay & withdraw collateral tx to get the number of accounts
113
+ const klendIxs = await buildRepayWithCollateralIxs(
114
+ kaminoMarket,
115
+ debtReserve,
116
+ collReserve,
117
+ obligation,
118
+ referrer,
119
+ currentSlot,
120
+ budgetAndPriorityFeeIxs,
121
+ scopeRefresh,
122
+ {
123
+ preActionIxs: [],
124
+ swapIxs: [],
125
+ lookupTables: [],
126
+ },
127
+ isClosingPosition,
128
+ repayAmountLamports,
129
+ withdrawableCollLamports
130
+ );
131
+ const uniqueKlendAccounts = uniqueAccounts(klendIxs);
132
+ const swapQuote = await quoter(swapQuoteInputs, uniqueKlendAccounts);
133
+
134
+ const swapQuotePxDebtToColl = swapQuote.priceAInB;
135
+ const collSwapInLamports = flashRepayAmountLamports.div(debtReserve.getMintFactor()).div(swapQuotePxDebtToColl).mul(collReserve.getMintFactor()).ceil();
94
136
 
95
137
  return {
96
138
  swapInputs: {
97
- inputAmountLamports: numberToLamportsDecimal(repayCalcs.collToSwapIn, collReserve!.stats.decimals)
98
- .ceil()
99
- .toNumber(),
139
+ inputAmountLamports: collSwapInLamports,
100
140
  inputMint: collTokenMint,
101
141
  outputMint: debtTokenMint,
102
142
  },
103
143
  initialInputs: {
104
- repayAmount,
105
- priceDebtToColl,
106
- slippagePct,
144
+ debtRepayAmountLamports: repayAmountLamports,
145
+ flashRepayAmountLamports,
146
+ swapQuote,
107
147
  currentSlot,
148
+ klendAccounts: uniqueKlendAccounts,
108
149
  },
109
150
  };
110
- };
151
+ }
111
152
 
112
- export const getRepayWithCollIxns = async (props: {
113
- kaminoMarket: KaminoMarket;
114
- budgetAndPriorityFeeIxns: TransactionInstruction[];
115
- amount: Decimal;
116
- debtTokenMint: PublicKey;
117
- collTokenMint: PublicKey;
118
- owner: PublicKey;
119
- priceDebtToColl: Decimal;
120
- slippagePct: Decimal;
121
- isClosingPosition: boolean;
122
- obligation: KaminoObligation;
123
- referrer: PublicKey;
124
- swapper: SwapIxnsProvider;
125
- currentSlot: number;
126
- getTotalKlendAccountsOnly: boolean;
127
- scopeRefresh: ScopeRefresh;
128
- }): Promise<{
129
- ixns: TransactionInstruction[];
130
- lookupTablesAddresses: PublicKey[];
131
- swapInputs: SwapInputs;
132
- totalKlendAccounts: number;
133
- initialInputs: InitialInputs;
134
- }> => {
135
- const {
136
- kaminoMarket,
137
- budgetAndPriorityFeeIxns,
138
- amount,
139
- debtTokenMint,
153
+ interface RepayWithCollIxsProps<QuoteResponse> extends RepayWithCollSwapInputsProps<QuoteResponse> {
154
+ swapper: SwapQuoteIxsProvider<QuoteResponse>;
155
+ logger?: (msg: string, ...extra: any[]) => void;
156
+ }
157
+
158
+ export async function getRepayWithCollIxs<QuoteResponse>({
159
+ repayAmount,
160
+ isClosingPosition,
161
+ budgetAndPriorityFeeIxs,
162
+ collTokenMint,
163
+ currentSlot,
164
+ debtTokenMint,
165
+ kaminoMarket,
166
+ obligation,
167
+ quoter,
168
+ swapper,
169
+ referrer,
170
+ scopeRefresh,
171
+ logger = console.log,
172
+ }: RepayWithCollIxsProps<QuoteResponse>): Promise<RepayWithCollIxsResponse<QuoteResponse>> {
173
+ const { swapInputs, initialInputs } = await getRepayWithCollSwapInputs({
140
174
  collTokenMint,
141
- owner,
142
- priceDebtToColl,
143
- slippagePct,
144
- isClosingPosition,
175
+ currentSlot,
176
+ debtTokenMint,
177
+ kaminoMarket,
145
178
  obligation,
179
+ quoter,
146
180
  referrer,
147
- swapper,
148
- currentSlot,
149
- getTotalKlendAccountsOnly,
181
+ repayAmount,
182
+ isClosingPosition,
183
+ budgetAndPriorityFeeIxs,
150
184
  scopeRefresh,
151
- } = props;
185
+ });
186
+ const { debtRepayAmountLamports, flashRepayAmountLamports, swapQuote } = initialInputs;
187
+ const { inputAmountLamports: collSwapInLamports } = swapInputs;
152
188
 
153
- const connection = kaminoMarket.getConnection();
154
- const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
155
- const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
156
- // const solTokenReserve = kaminoMarket.getReserveByMint(WRAPPED_SOL_MINT);
157
- const flashLoanFeePct = debtReserve?.getFlashLoanFee() || new Decimal(0);
189
+ const collReserve = kaminoMarket.getReserveByMint(collTokenMint)!;
190
+ const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint)!;
158
191
 
159
- const irSlippageBpsForDebt = obligation!
160
- .estimateObligationInterestRate(
161
- kaminoMarket,
162
- debtReserve!,
163
- obligation?.state.borrows.find((borrow) => borrow.borrowReserve?.equals(debtReserve!.address))!,
164
- currentSlot
165
- )
166
- .toDecimalPlaces(debtReserve?.state.liquidity.mintDecimals.toNumber()!, Decimal.ROUND_CEIL);
167
- // add 0.1% to irSlippageBpsForDebt because we don't want to estimate slightly less than SC and end up not reapying enough
168
- const repayAmount = amount
169
- .mul(irSlippageBpsForDebt.mul(new Decimal('1.001')))
170
- .toDecimalPlaces(debtReserve?.state.liquidity.mintDecimals.toNumber()!, Decimal.ROUND_CEIL);
192
+ logger(
193
+ `Expected to swap in: ${collSwapInLamports.div(collReserve.getMintFactor())} ${
194
+ collReserve.symbol
195
+ }, for: ${flashRepayAmountLamports.div(debtReserve.getMintFactor())} ${debtReserve.symbol}, quoter px: ${
196
+ swapQuote.priceAInB
197
+ } ${debtReserve.symbol}/${collReserve.symbol}`
198
+ );
171
199
 
172
- const calcs = repayWithCollCalcs({
173
- repayAmount,
174
- priceDebtToColl,
175
- slippagePct,
176
- flashLoanFeePct,
177
- });
200
+ const swapResponse = await swapper(swapInputs, initialInputs.klendAccounts, swapQuote);
201
+ const ixs = await buildRepayWithCollateralIxs(
202
+ kaminoMarket,
203
+ debtReserve,
204
+ collReserve,
205
+ obligation,
206
+ referrer,
207
+ currentSlot,
208
+ budgetAndPriorityFeeIxs,
209
+ scopeRefresh,
210
+ swapResponse,
211
+ isClosingPosition,
212
+ debtRepayAmountLamports,
213
+ swapInputs.inputAmountLamports
214
+ );
178
215
 
179
- console.log('Ops Calcs', toJson(calcs));
216
+ return {
217
+ ixs,
218
+ lookupTables: swapResponse.lookupTables,
219
+ swapInputs,
220
+ initialInputs,
221
+ };
222
+ }
223
+
224
+ async function buildRepayWithCollateralIxs(
225
+ market: KaminoMarket,
226
+ debtReserve: KaminoReserve,
227
+ collReserve: KaminoReserve,
228
+ obligation: KaminoObligation,
229
+ referrer: PublicKey,
230
+ currentSlot: number,
231
+ budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
232
+ scopeRefresh: ScopeRefresh | undefined,
233
+ swapQuoteIxs: SwapQuoteIxs,
234
+ isClosingPosition: boolean,
235
+ debtRepayAmountLamports: Decimal,
236
+ collWithdrawLamports: Decimal
237
+ ): Promise<TransactionInstruction[]> {
238
+ // 1. Create atas & budget txns
239
+ const budgetIxns = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxns(1_400_000);
180
240
 
181
- // // 1. Create atas & budget txns
182
- const mintsToCreateAtas = [collTokenMint, debtTokenMint, collReserve!.getCTokenMint()];
183
- const mintsToCreateAtasTokenPrograms = [
184
- collReserve?.getLiquidityTokenProgram()!,
185
- debtReserve?.getLiquidityTokenProgram()!,
186
- TOKEN_PROGRAM_ID,
241
+ const atas = [
242
+ { mint: collReserve.getLiquidityMint(), tokenProgram: collReserve.getLiquidityTokenProgram() },
243
+ { mint: debtReserve.getLiquidityMint(), tokenProgram: debtReserve.getLiquidityTokenProgram() },
244
+ { mint: collReserve.getCTokenMint(), tokenProgram: TOKEN_PROGRAM_ID },
187
245
  ];
188
246
 
189
- const budgetIxns = budgetAndPriorityFeeIxns || getComputeBudgetAndPriorityFeeIxns(3000000);
190
- const {
191
- atas: [, debtTokenAta],
192
- createAtasIxns,
193
- closeAtasIxns,
194
- } = await getAtasWithCreateIxnsIfMissing(connection, owner, mintsToCreateAtas, mintsToCreateAtasTokenPrograms);
247
+ const atasAndIxs = createAtasIdempotent(obligation.state.owner, atas);
248
+ const [, { ata: debtTokenAta }] = atasAndIxs;
195
249
 
196
- // 1. Flash borrow & repay the debt to repay amount needed
250
+ // 2. Flash borrow & repay the debt to repay amount needed
197
251
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
198
- borrowIxnIndex: budgetIxns.length + createAtasIxns.length,
199
- walletPublicKey: owner,
200
- lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
201
- lendingMarketAddress: kaminoMarket.getAddress(),
202
- reserve: debtReserve!,
203
- amountLamports: numberToLamportsDecimal(repayAmount, debtReserve!.stats.decimals).floor(),
252
+ borrowIxnIndex: budgetIxns.length + atasAndIxs.length,
253
+ walletPublicKey: obligation.state.owner,
254
+ lendingMarketAuthority: market.getLendingMarketAuthority(),
255
+ lendingMarketAddress: market.getAddress(),
256
+ reserve: debtReserve,
257
+ amountLamports: debtRepayAmountLamports,
204
258
  destinationAta: debtTokenAta,
205
- referrerAccount: kaminoMarket.programId,
206
- referrerTokenState: kaminoMarket.programId,
207
- programId: kaminoMarket.programId,
259
+ referrerAccount: market.programId,
260
+ referrerTokenState: market.programId,
261
+ programId: market.programId,
208
262
  });
209
263
 
210
- const requestElevationGroup = obligation.state.elevationGroup !== 0 ? true : false;
264
+ const requestElevationGroup = !isClosingPosition && obligation.state.elevationGroup !== 0;
211
265
 
212
- // 2. Repay using the flash borrowed funds & withdraw collateral to swap and pay the flash loan
266
+ // 3. Repay using the flash borrowed funds & withdraw collateral to swap and pay the flash loan
213
267
  const repayAndWithdrawAction = await KaminoAction.buildRepayAndWithdrawTxns(
214
- kaminoMarket,
215
- isClosingPosition ? U64_MAX : numberToLamportsDecimal(repayAmount, debtReserve!.stats.decimals).floor().toString(),
216
- new PublicKey(debtTokenMint),
217
- isClosingPosition
218
- ? U64_MAX
219
- : numberToLamportsDecimal(calcs.collToSwapIn, collReserve!.stats.decimals).ceil().toString(),
220
- new PublicKey(collTokenMint),
221
- owner,
268
+ market,
269
+ isClosingPosition ? U64_MAX : debtRepayAmountLamports.toString(),
270
+ debtReserve.getLiquidityMint(),
271
+ isClosingPosition ? U64_MAX : collWithdrawLamports.toString(),
272
+ collReserve.getLiquidityMint(),
273
+ obligation.state.owner,
222
274
  currentSlot,
223
275
  obligation,
224
276
  0,
@@ -230,89 +282,17 @@ export const getRepayWithCollIxns = async (props: {
230
282
  scopeRefresh
231
283
  );
232
284
 
233
- const ixns = [
285
+ // 4. Swap collateral to debt to repay flash loan
286
+ const { preActionIxs, swapIxs } = swapQuoteIxs;
287
+ const swapInstructions = removeBudgetAndAtaIxns(swapIxs, []);
288
+
289
+ return [
234
290
  ...budgetIxns,
235
- ...createAtasIxns,
236
- ...[flashBorrowIxn],
237
- ...repayAndWithdrawAction.setupIxs,
238
- ...[repayAndWithdrawAction.lendingIxs[0]],
239
- ...repayAndWithdrawAction.inBetweenIxs,
240
- ...[repayAndWithdrawAction.lendingIxs[1]],
241
- ...repayAndWithdrawAction.cleanupIxs,
242
- ...[flashRepayIxn],
243
- ...closeAtasIxns,
291
+ ...atasAndIxs.map((x) => x.createAtaIx),
292
+ flashBorrowIxn,
293
+ ...preActionIxs,
294
+ ...KaminoAction.actionToIxs(repayAndWithdrawAction),
295
+ ...swapInstructions,
296
+ flashRepayIxn,
244
297
  ];
245
-
246
- const uniqueAccounts = new PublicKeySet<PublicKey>([]);
247
- ixns.forEach((ixn) => {
248
- ixn.keys.forEach((key) => {
249
- uniqueAccounts.add(key.pubkey);
250
- });
251
- });
252
- const totalKlendAccounts = uniqueAccounts.toArray().length;
253
-
254
- // return early to avoid extra swapper calls
255
- if (getTotalKlendAccountsOnly) {
256
- return {
257
- ixns: [],
258
- lookupTablesAddresses: [],
259
- swapInputs: { inputAmountLamports: 0, inputMint: PublicKey.default, outputMint: PublicKey.default },
260
- totalKlendAccounts: totalKlendAccounts,
261
- initialInputs: {
262
- repayAmount,
263
- priceDebtToColl,
264
- slippagePct,
265
- currentSlot,
266
- },
267
- };
268
- }
269
-
270
- console.log(
271
- 'Expected to swap in',
272
- calcs.collToSwapIn.toString(),
273
- 'coll for',
274
- calcs.swapDebtExpectedOut.toString(),
275
- 'debt'
276
- );
277
-
278
- const swapInputs: SwapInputs = {
279
- inputAmountLamports: numberToLamportsDecimal(calcs.collToSwapIn, collReserve!.stats.decimals).ceil().toNumber(),
280
- inputMint: collTokenMint,
281
- outputMint: debtTokenMint,
282
- };
283
-
284
- // 3. Swap collateral to debt to repay flash loan
285
- const [swapIxns, lookupTablesAddresses] = await swapper(
286
- swapInputs.inputAmountLamports,
287
- swapInputs.inputMint,
288
- swapInputs.outputMint,
289
- slippagePct.toNumber()
290
- );
291
-
292
- const swapInstructions = removeBudgetAndAtaIxns(swapIxns, []);
293
-
294
- return {
295
- ixns: [
296
- ...budgetIxns,
297
- ...createAtasIxns,
298
- ...[flashBorrowIxn],
299
- ...repayAndWithdrawAction.setupIxs,
300
- ...[repayAndWithdrawAction.lendingIxs[0]],
301
- ...repayAndWithdrawAction.inBetweenIxs,
302
- ...[repayAndWithdrawAction.lendingIxs[1]],
303
- ...repayAndWithdrawAction.cleanupIxs,
304
- ...swapInstructions,
305
- ...[flashRepayIxn],
306
- ...closeAtasIxns,
307
- ],
308
- lookupTablesAddresses,
309
- swapInputs,
310
- totalKlendAccounts,
311
- initialInputs: {
312
- repayAmount,
313
- priceDebtToColl,
314
- slippagePct,
315
- currentSlot,
316
- },
317
- };
318
- };
298
+ }