@kamino-finance/klend-sdk 5.11.3-beta.1 → 5.11.4

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 (65) hide show
  1. package/dist/classes/action.d.ts +23 -23
  2. package/dist/classes/action.d.ts.map +1 -1
  3. package/dist/classes/action.js +122 -195
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/index.d.ts +1 -0
  6. package/dist/classes/index.d.ts.map +1 -1
  7. package/dist/classes/index.js +1 -0
  8. package/dist/classes/index.js.map +1 -1
  9. package/dist/classes/manager.d.ts +6 -1
  10. package/dist/classes/manager.d.ts.map +1 -1
  11. package/dist/classes/manager.js +16 -1
  12. package/dist/classes/manager.js.map +1 -1
  13. package/dist/classes/market.d.ts +3 -3
  14. package/dist/classes/market.d.ts.map +1 -1
  15. package/dist/classes/market.js +30 -16
  16. package/dist/classes/market.js.map +1 -1
  17. package/dist/classes/obligation.d.ts +2 -0
  18. package/dist/classes/obligation.d.ts.map +1 -1
  19. package/dist/classes/obligation.js +5 -0
  20. package/dist/classes/obligation.js.map +1 -1
  21. package/dist/classes/vault.js +1 -1
  22. package/dist/classes/vault.js.map +1 -1
  23. package/dist/lending_operations/repay_with_collateral_operations.d.ts +4 -4
  24. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  25. package/dist/lending_operations/repay_with_collateral_operations.js +10 -8
  26. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  27. package/dist/lending_operations/swap_collateral_operations.d.ts +2 -2
  28. package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
  29. package/dist/lending_operations/swap_collateral_operations.js +11 -6
  30. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  31. package/dist/leverage/calcs.d.ts +5 -10
  32. package/dist/leverage/calcs.d.ts.map +1 -1
  33. package/dist/leverage/calcs.js +6 -13
  34. package/dist/leverage/calcs.js.map +1 -1
  35. package/dist/leverage/operations.d.ts +9 -7
  36. package/dist/leverage/operations.d.ts.map +1 -1
  37. package/dist/leverage/operations.js +78 -72
  38. package/dist/leverage/operations.js.map +1 -1
  39. package/dist/leverage/types.d.ts +4 -4
  40. package/dist/leverage/types.d.ts.map +1 -1
  41. package/dist/utils/ObligationType.d.ts +1 -1
  42. package/dist/utils/ObligationType.d.ts.map +1 -1
  43. package/dist/utils/managerTypes.d.ts.map +1 -1
  44. package/dist/utils/managerTypes.js +7 -52
  45. package/dist/utils/managerTypes.js.map +1 -1
  46. package/dist/utils/oracle.d.ts +3 -3
  47. package/dist/utils/oracle.d.ts.map +1 -1
  48. package/dist/utils/oracle.js +4 -3
  49. package/dist/utils/oracle.js.map +1 -1
  50. package/package.json +2 -2
  51. package/src/classes/action.ts +143 -211
  52. package/src/classes/index.ts +1 -0
  53. package/src/classes/manager.ts +32 -1
  54. package/src/classes/market.ts +34 -25
  55. package/src/classes/obligation.ts +6 -0
  56. package/src/classes/vault.ts +1 -1
  57. package/src/client.ts +8 -3
  58. package/src/lending_operations/repay_with_collateral_operations.ts +15 -11
  59. package/src/lending_operations/swap_collateral_operations.ts +19 -7
  60. package/src/leverage/calcs.ts +2 -18
  61. package/src/leverage/operations.ts +114 -72
  62. package/src/leverage/types.ts +4 -4
  63. package/src/utils/ObligationType.ts +1 -1
  64. package/src/utils/managerTypes.ts +10 -52
  65. package/src/utils/oracle.ts +7 -6
@@ -9,3 +9,4 @@ export * from './jupiterPerps';
9
9
  export * from './manager';
10
10
  export * from './vault';
11
11
  export * from './fraction';
12
+ export * from './types';
@@ -575,6 +575,37 @@ export class KaminoManager {
575
575
  return this._vaultClient.getAllVaults();
576
576
  }
577
577
 
578
+ /**
579
+ * Get all lending markets
580
+ * @returns an array of all lending markets
581
+ */
582
+ async getAllMarkets(): Promise<KaminoMarket[]> {
583
+ const lendingMarketsAccounts = await getProgramAccounts(
584
+ this.getConnection(),
585
+ this._kaminoLendProgramId,
586
+ LendingMarket.layout.span + 8,
587
+ {
588
+ commitment: this.getConnection().commitment ?? 'processed',
589
+ filters: [
590
+ { dataSize: LendingMarket.layout.span + 8 },
591
+ { memcmp: { offset: 0, bytes: bs58.encode(LendingMarket.discriminator) } },
592
+ ],
593
+ }
594
+ );
595
+
596
+ const markets = await Promise.all(
597
+ lendingMarketsAccounts.map((account) =>
598
+ KaminoMarket.load(
599
+ this._connection,
600
+ account.pubkey,
601
+ this.recentSlotDurationMs,
602
+ this._kaminoLendProgramId
603
+ )
604
+ )
605
+ );
606
+ return markets.filter((market): market is KaminoMarket => market !== null);
607
+ }
608
+
578
609
  /**
579
610
  * Get all vaults for owner
580
611
  * @param owner the pubkey of the vaults owner
@@ -949,7 +980,7 @@ export class KaminoManager {
949
980
  }
950
981
 
951
982
  /**
952
- * This retruns an array of scope oracle configs to be used to set the scope price and twap oracles for a reserve
983
+ * This returns an array of scope oracle configs to be used to set the scope price and twap oracles for a reserve
953
984
  * @param feed - scope feed to fetch prices from
954
985
  * @param cluster - cluster to fetch from, this should be left unchanged unless working on devnet or locally
955
986
  * @returns - an array of scope oracle configs
@@ -29,7 +29,7 @@ import Decimal from 'decimal.js';
29
29
  import { FarmState } from '@kamino-finance/farms-sdk';
30
30
  import { PROGRAM_ID } from '../idl_codegen/programId';
31
31
  import bs58 from 'bs58';
32
- import { OraclePrices, Scope } from '@kamino-finance/scope-sdk';
32
+ import { OraclePrices, Scope, U16_MAX } from '@kamino-finance/scope-sdk';
33
33
  import { Fraction } from './fraction';
34
34
  import { chunks, KaminoPrices, MintToPriceMap } from '@kamino-finance/kliquidity-sdk';
35
35
  import { parseTokenSymbol, parseZeroPaddedUtf8 } from './utils';
@@ -59,8 +59,6 @@ export class KaminoMarket {
59
59
 
60
60
  readonly programId: PublicKey;
61
61
 
62
- scope: Scope;
63
-
64
62
  private readonly recentSlotDurationMs: number;
65
63
 
66
64
  private constructor(
@@ -68,7 +66,6 @@ export class KaminoMarket {
68
66
  state: LendingMarket,
69
67
  marketAddress: string,
70
68
  reserves: Map<PublicKey, KaminoReserve>,
71
- scope: Scope,
72
69
  recentSlotDurationMs: number,
73
70
  programId: PublicKey = PROGRAM_ID
74
71
  ) {
@@ -78,7 +75,6 @@ export class KaminoMarket {
78
75
  this.reserves = reserves;
79
76
  this.reservesActive = getReservesActive(this.reserves);
80
77
  this.programId = programId;
81
- this.scope = scope;
82
78
  this.recentSlotDurationMs = recentSlotDurationMs;
83
79
  }
84
80
 
@@ -97,7 +93,6 @@ export class KaminoMarket {
97
93
  marketAddress: PublicKey,
98
94
  recentSlotDurationMs: number,
99
95
  programId: PublicKey = PROGRAM_ID,
100
- setupLocalTest: boolean = false,
101
96
  withReserves: boolean = true
102
97
  ) {
103
98
  const market = await LendingMarket.fetch(connection, marketAddress, programId);
@@ -105,26 +100,12 @@ export class KaminoMarket {
105
100
  if (market === null) {
106
101
  return null;
107
102
  }
108
- let scope: Scope;
109
- if (!setupLocalTest) {
110
- scope = new Scope('mainnet-beta', connection);
111
- } else {
112
- scope = new Scope('localnet', connection);
113
- }
114
103
 
115
104
  const reserves = withReserves
116
105
  ? await getReservesForMarket(marketAddress, connection, programId, recentSlotDurationMs)
117
106
  : new Map<PublicKey, KaminoReserve>();
118
107
 
119
- return new KaminoMarket(
120
- connection,
121
- market,
122
- marketAddress.toString(),
123
- reserves,
124
- scope,
125
- recentSlotDurationMs,
126
- programId
127
- );
108
+ return new KaminoMarket(connection, market, marketAddress.toString(), reserves, recentSlotDurationMs, programId);
128
109
  }
129
110
 
130
111
  async reload(): Promise<void> {
@@ -1186,9 +1167,9 @@ export class KaminoMarket {
1186
1167
  /**
1187
1168
  * Get all Scope prices used by all the market reserves
1188
1169
  */
1189
- async getAllScopePrices(oraclePrices?: OraclePrices): Promise<KaminoPrices> {
1170
+ async getAllScopePrices(scope: Scope, oraclePrices?: OraclePrices): Promise<KaminoPrices> {
1190
1171
  if (!oraclePrices) {
1191
- oraclePrices = await this.scope.getOraclePrices();
1172
+ oraclePrices = await scope.getOraclePrices();
1192
1173
  }
1193
1174
  const spot: MintToPriceMap = {};
1194
1175
  const twaps: MintToPriceMap = {};
@@ -1199,11 +1180,11 @@ export class KaminoMarket {
1199
1180
  const chain = reserve.state.config.tokenInfo.scopeConfiguration.priceChain;
1200
1181
  const twapChain = reserve.state.config.tokenInfo.scopeConfiguration.twapChain.filter((x) => x > 0);
1201
1182
  if (oracle && isNotNullPubkey(oracle) && chain && Scope.isScopeChainValid(chain)) {
1202
- const spotPrice = await this.scope.getPriceFromChain(chain, oraclePrices);
1183
+ const spotPrice = await scope.getPriceFromChain(chain, oraclePrices);
1203
1184
  spot[tokenMint] = { price: spotPrice.price, name: tokenName };
1204
1185
  }
1205
1186
  if (oracle && isNotNullPubkey(oracle) && twapChain && Scope.isScopeChainValid(twapChain)) {
1206
- const twap = await this.scope.getPriceFromChain(twapChain, oraclePrices);
1187
+ const twap = await scope.getPriceFromChain(twapChain, oraclePrices);
1207
1188
  twaps[tokenMint] = { price: twap.price, name: tokenName };
1208
1189
  }
1209
1190
  }
@@ -1527,6 +1508,34 @@ export function getReservesActive(reserves: Map<PublicKey, KaminoReserve>): Map<
1527
1508
  return reservesActive;
1528
1509
  }
1529
1510
 
1511
+ export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: PublicKey[]): number[] {
1512
+ const tokenIds: number[] = [];
1513
+
1514
+ for (const reserveAddress of reserves) {
1515
+ const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
1516
+ if (!reserve) {
1517
+ throw new Error(`Reserve not found for reserve ${reserveAddress.toBase58()}`);
1518
+ }
1519
+
1520
+ if (!reserve.state.config.tokenInfo.scopeConfiguration.priceFeed.equals(PublicKey.default)) {
1521
+ let x = 0;
1522
+
1523
+ while (reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x] !== U16_MAX) {
1524
+ tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x]);
1525
+ x++;
1526
+ }
1527
+
1528
+ x = 0;
1529
+ while (reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x] !== U16_MAX) {
1530
+ tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x]);
1531
+ x++;
1532
+ }
1533
+ }
1534
+ }
1535
+
1536
+ return tokenIds;
1537
+ }
1538
+
1530
1539
  export async function getReserveFromMintAndMarket(
1531
1540
  connection: Connection,
1532
1541
  market: KaminoMarket,
@@ -17,6 +17,7 @@ import {
17
17
  getObligationPdaWithArgs,
18
18
  getObligationType,
19
19
  isNotNullPubkey,
20
+ ObligationType,
20
21
  PubkeyHashMap,
21
22
  TOTAL_NUMBER_OF_IDS_TO_CHECK,
22
23
  U64_MAX,
@@ -1593,3 +1594,8 @@ export class KaminoObligation {
1593
1594
  }
1594
1595
  }
1595
1596
  }
1597
+
1598
+ // Create a function that checks if an obligation is of type obligation or obligationType
1599
+ export function isKaminoObligation(obligation: KaminoObligation | ObligationType): obligation is KaminoObligation {
1600
+ return 'obligationAddress' in obligation;
1601
+ }
@@ -301,7 +301,7 @@ export class KaminoVaultClient {
301
301
  ctokenVault: cTokenVault,
302
302
  systemProgram: SystemProgram.programId,
303
303
  rent: SYSVAR_RENT_PUBKEY,
304
- reserveCollateralTokenProgram: vaultState.tokenProgram,
304
+ reserveCollateralTokenProgram: TOKEN_PROGRAM_ID,
305
305
  };
306
306
 
307
307
  const updateReserveAllocationArgs: UpdateReserveAllocationArgs = {
package/src/client.ts CHANGED
@@ -22,6 +22,7 @@ import { VanillaObligation } from './utils/ObligationType';
22
22
  import { parseTokenSymbol } from './classes/utils';
23
23
  import { Env, initEnv } from '../tests/runner/setup_utils';
24
24
  import { initializeFarmsForReserve } from '../tests/runner/farms/farms_operations';
25
+ import { Scope } from '@kamino-finance/scope-sdk';
25
26
 
26
27
  const STAGING_LENDING_MARKET = new PublicKey('6WVSwDQXrBZeQVnu6hpnsRZhodaJTZBUaC334SiiBKdb');
27
28
  const MAINNET_LENDING_MARKET = new PublicKey('7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF');
@@ -309,7 +310,8 @@ async function deposit(connection: Connection, wallet: Keypair, token: string, d
309
310
  kaminoMarket.getReserveBySymbol(token)!.getLiquidityMint(),
310
311
  wallet.publicKey,
311
312
  new VanillaObligation(STAGING_LENDING_MARKET),
312
- true
313
+ true,
314
+ { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
313
315
  );
314
316
  console.log('User obligation', kaminoAction.obligation!.obligationAddress.toString());
315
317
 
@@ -330,7 +332,8 @@ async function withdraw(connection: Connection, wallet: Keypair, token: string,
330
332
  kaminoMarket.getReserveBySymbol(token)!.getLiquidityMint(),
331
333
  wallet.publicKey,
332
334
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
333
- true
335
+ true,
336
+ { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
334
337
  );
335
338
  console.log('User obligation', kaminoAction.obligation!.obligationAddress.toString());
336
339
 
@@ -351,7 +354,8 @@ async function borrow(connection: Connection, wallet: Keypair, token: string, bo
351
354
  kaminoMarket.getReserveBySymbol(token)!.getLiquidityMint(),
352
355
  wallet.publicKey,
353
356
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
354
- true
357
+ true,
358
+ { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
355
359
  );
356
360
  console.log('User obligation', kaminoAction.obligation!.obligationAddress.toString());
357
361
 
@@ -373,6 +377,7 @@ async function repay(connection: Connection, wallet: Keypair, token: string, bor
373
377
  wallet.publicKey,
374
378
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
375
379
  true,
380
+ { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' },
376
381
  await connection.getSlot()
377
382
  );
378
383
  console.log('User obligation', kaminoAction.obligation!.obligationAddress.toString());
@@ -6,12 +6,13 @@ import {
6
6
  SwapIxs,
7
7
  SwapIxsProvider,
8
8
  SwapQuoteProvider,
9
+ getScopeRefreshIx,
9
10
  } from '../leverage';
10
11
  import {
11
12
  createAtasIdempotent,
12
13
  getComputeBudgetAndPriorityFeeIxns,
13
14
  removeBudgetAndAtaIxns,
14
- ScopeRefresh,
15
+ ScopePriceRefreshConfig,
15
16
  U64_MAX,
16
17
  uniqueAccounts,
17
18
  } from '../utils';
@@ -51,7 +52,7 @@ interface RepayWithCollSwapInputsProps<QuoteResponse> {
51
52
  repayAmount: Decimal;
52
53
  isClosingPosition: boolean;
53
54
  budgetAndPriorityFeeIxs?: TransactionInstruction[];
54
- scopeRefresh?: ScopeRefresh;
55
+ scopeRefreshConfig?: ScopePriceRefreshConfig;
55
56
  useV2Ixs: boolean;
56
57
  quoter: SwapQuoteProvider<QuoteResponse>;
57
58
  }
@@ -67,7 +68,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
67
68
  repayAmount,
68
69
  isClosingPosition,
69
70
  budgetAndPriorityFeeIxs,
70
- scopeRefresh,
71
+ scopeRefreshConfig,
71
72
  useV2Ixs,
72
73
  }: RepayWithCollSwapInputsProps<QuoteResponse>): Promise<{
73
74
  swapInputs: SwapInputs;
@@ -126,7 +127,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
126
127
  referrer,
127
128
  currentSlot,
128
129
  budgetAndPriorityFeeIxs,
129
- scopeRefresh,
130
+ scopeRefreshConfig,
130
131
  {
131
132
  preActionIxs: [],
132
133
  swapIxs: [],
@@ -191,7 +192,7 @@ export async function getRepayWithCollIxs<QuoteResponse>({
191
192
  quoter,
192
193
  swapper,
193
194
  referrer,
194
- scopeRefresh,
195
+ scopeRefreshConfig,
195
196
  useV2Ixs,
196
197
  logger = console.log,
197
198
  }: RepayWithCollIxsProps<QuoteResponse>): Promise<RepayWithCollIxsResponse<QuoteResponse>> {
@@ -206,7 +207,7 @@ export async function getRepayWithCollIxs<QuoteResponse>({
206
207
  repayAmount,
207
208
  isClosingPosition,
208
209
  budgetAndPriorityFeeIxs,
209
- scopeRefresh,
210
+ scopeRefreshConfig,
210
211
  useV2Ixs,
211
212
  });
212
213
  const { debtRepayAmountLamports, flashRepayAmountLamports, maxCollateralWithdrawLamports, swapQuote } = initialInputs;
@@ -244,7 +245,7 @@ export async function getRepayWithCollIxs<QuoteResponse>({
244
245
  referrer,
245
246
  currentSlot,
246
247
  budgetAndPriorityFeeIxs,
247
- scopeRefresh,
248
+ scopeRefreshConfig,
248
249
  swapResponse,
249
250
  isClosingPosition,
250
251
  debtRepayAmountLamports,
@@ -268,7 +269,7 @@ async function buildRepayWithCollateralIxs(
268
269
  referrer: PublicKey,
269
270
  currentSlot: number,
270
271
  budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
271
- scopeRefresh: ScopeRefresh | undefined,
272
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
272
273
  swapQuoteIxs: SwapIxs,
273
274
  isClosingPosition: boolean,
274
275
  debtRepayAmountLamports: Decimal,
@@ -286,9 +287,11 @@ async function buildRepayWithCollateralIxs(
286
287
  const atasAndIxs = createAtasIdempotent(obligation.state.owner, atas);
287
288
  const [, { ata: debtTokenAta }] = atasAndIxs;
288
289
 
290
+ const scopeRefreshIxn = await getScopeRefreshIx(market, collReserve, debtReserve, obligation, scopeRefreshConfig);
291
+
289
292
  // 2. Flash borrow & repay the debt to repay amount needed
290
293
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
291
- borrowIxnIndex: budgetIxns.length + atasAndIxs.length,
294
+ borrowIxnIndex: budgetIxns.length + atasAndIxs.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
292
295
  walletPublicKey: obligation.state.owner,
293
296
  lendingMarketAuthority: market.getLendingMarketAuthority(),
294
297
  lendingMarketAddress: market.getAddress(),
@@ -314,13 +317,13 @@ async function buildRepayWithCollateralIxs(
314
317
  currentSlot,
315
318
  obligation,
316
319
  useV2Ixs,
320
+ undefined,
317
321
  0,
318
322
  false,
319
323
  requestElevationGroup,
320
324
  undefined,
321
325
  undefined,
322
- referrer,
323
- scopeRefresh
326
+ referrer
324
327
  );
325
328
 
326
329
  // 4. Swap collateral to debt to repay flash loan
@@ -328,6 +331,7 @@ async function buildRepayWithCollateralIxs(
328
331
  const swapInstructions = removeBudgetAndAtaIxns(swapIxs, []);
329
332
 
330
333
  return [
334
+ ...scopeRefreshIxn,
331
335
  ...budgetIxns,
332
336
  ...atasAndIxs.map((x) => x.createAtaIx),
333
337
  flashBorrowIxn,
@@ -6,14 +6,14 @@ import {
6
6
  KaminoObligation,
7
7
  KaminoReserve,
8
8
  } from '../classes';
9
- import { getFlashLoanInstructions, SwapIxsProvider, SwapQuoteProvider } from '../leverage';
9
+ import { getFlashLoanInstructions, getScopeRefreshIx, SwapIxsProvider, SwapQuoteProvider } from '../leverage';
10
10
  import {
11
11
  createAtasIdempotent,
12
12
  DEFAULT_MAX_COMPUTE_UNITS,
13
13
  getAssociatedTokenAddress,
14
14
  getComputeBudgetAndPriorityFeeIxns,
15
15
  PublicKeySet,
16
- ScopeRefresh,
16
+ ScopePriceRefreshConfig,
17
17
  U64_MAX,
18
18
  uniqueAccounts,
19
19
  } from '../utils';
@@ -61,7 +61,7 @@ export interface SwapCollIxnsInputs<QuoteResponse> {
61
61
  referrer: PublicKey;
62
62
  currentSlot: number;
63
63
  budgetAndPriorityFeeIxns?: TransactionInstruction[];
64
- scopeRefresh?: ScopeRefresh;
64
+ scopeRefreshConfig?: ScopePriceRefreshConfig;
65
65
  useV2Ixs: boolean;
66
66
  quoter: SwapQuoteProvider<QuoteResponse>;
67
67
  swapper: SwapIxsProvider<QuoteResponse>;
@@ -205,7 +205,7 @@ type SwapCollContext<QuoteResponse> = {
205
205
  referrer: PublicKey;
206
206
  currentSlot: number;
207
207
  useV2Ixs: boolean;
208
- scopeRefresh: ScopeRefresh | undefined;
208
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined;
209
209
  logger: (msg: string, ...extra: any[]) => void;
210
210
  };
211
211
 
@@ -235,7 +235,7 @@ function extractArgsAndContext<QuoteResponse>(
235
235
  quoter: inputs.quoter,
236
236
  swapper: inputs.swapper,
237
237
  referrer: inputs.referrer,
238
- scopeRefresh: inputs.scopeRefresh,
238
+ scopeRefreshConfig: inputs.scopeRefreshConfig,
239
239
  currentSlot: inputs.currentSlot,
240
240
  useV2Ixs: inputs.useV2Ixs,
241
241
  },
@@ -264,6 +264,18 @@ async function getKlendIxns(
264
264
  const { ataCreationIxns, targetCollAta } = getAtaCreationIxns(context);
265
265
  const setupIxns = [...context.budgetAndPriorityFeeIxns, ...ataCreationIxns];
266
266
 
267
+ const scopeRefreshIxn = await getScopeRefreshIx(
268
+ context.market,
269
+ context.sourceCollReserve,
270
+ context.targetCollReserve,
271
+ context.obligation,
272
+ context.scopeRefreshConfig
273
+ );
274
+
275
+ if (scopeRefreshIxn) {
276
+ setupIxns.unshift(...scopeRefreshIxn);
277
+ }
278
+
267
279
  const targetCollFlashBorrowedAmount = calculateTargetCollFlashBorrowedAmount(targetCollSwapOutAmount, context);
268
280
  const { targetCollFlashBorrowIxn, targetCollFlashRepayIxn } = getTargetCollFlashLoanIxns(
269
281
  targetCollFlashBorrowedAmount,
@@ -380,6 +392,7 @@ async function getDepositTargetCollIxns(
380
392
  context.obligation.state.owner,
381
393
  context.obligation,
382
394
  context.useV2Ixs,
395
+ undefined, // we create the scope refresh ixn outside of KaminoAction
383
396
  0, // no extra compute budget
384
397
  false, // we do not need ATA ixns here (we construct and close them ourselves)
385
398
  removesElevationGroup, // we may need to (temporarily) remove the elevation group; the same or a different one will be set on withdraw, if requested
@@ -387,7 +400,6 @@ async function getDepositTargetCollIxns(
387
400
  false, // we do not need to create a lookup table, dealing with an existing obligation
388
401
  context.referrer,
389
402
  context.currentSlot,
390
- context.scopeRefresh,
391
403
  removesElevationGroup ? 0 : undefined // only applicable when removing the group
392
404
  );
393
405
  return {
@@ -430,6 +442,7 @@ async function getWithdrawSourceCollIxns(
430
442
  context.obligation.state.owner,
431
443
  context.obligation,
432
444
  context.useV2Ixs,
445
+ undefined, // we create the scope refresh ixn outside of KaminoAction
433
446
  0, // no extra compute budget
434
447
  false, // we do not need ATA ixns here (we construct and close them ourselves)
435
448
  requestedElevationGroup !== undefined, // the `elevationGroupIdToRequestAfterWithdraw()` has already decided on this
@@ -437,7 +450,6 @@ async function getWithdrawSourceCollIxns(
437
450
  false, // we do not need to create a lookup table, dealing with an existing obligation
438
451
  context.referrer,
439
452
  context.currentSlot,
440
- undefined, // we have refreshed scope already, during depositing
441
453
  requestedElevationGroup,
442
454
  context.obligation.deposits.has(context.targetCollReserve.address) // if our obligation already had the target coll...
443
455
  ? undefined // ... then we need no customizations here, but otherwise...
@@ -35,7 +35,6 @@ export interface LeverageFormsCalcsArgs {
35
35
  targetLeverage: Decimal;
36
36
  activeTab: FormTabs;
37
37
  flashBorrowReserveFlashLoanFeePercentage: Decimal;
38
- borrowFee: Decimal;
39
38
  debtBorrowFactorPct: Decimal;
40
39
  priceCollToDebt: Decimal;
41
40
  priceDebtToColl: Decimal;
@@ -63,7 +62,6 @@ export async function calculateMultiplyEffects(
63
62
  targetLeverage,
64
63
  activeTab,
65
64
  flashBorrowReserveFlashLoanFeePercentage,
66
- borrowFee,
67
65
  debtBorrowFactorPct,
68
66
  priceCollToDebt,
69
67
  priceDebtToColl,
@@ -82,7 +80,6 @@ export async function calculateMultiplyEffects(
82
80
  selectedTokenMint,
83
81
  collTokenMint: collTokenMint,
84
82
  flashLoanFee: flashBorrowReserveFlashLoanFeePercentage,
85
- borrowFee,
86
83
  });
87
84
 
88
85
  // calculate estimations for withdraw operation
@@ -109,7 +106,6 @@ export async function calculateMultiplyEffects(
109
106
  totalDeposited: new Decimal(deposited),
110
107
  totalBorrowed: new Decimal(borrowed),
111
108
  flashLoanFee: flashBorrowReserveFlashLoanFeePercentage, // TODO: is this the right flash borrow?
112
- borrowFee,
113
109
  });
114
110
 
115
111
  if (logEstimations) {
@@ -195,13 +191,11 @@ export const calcBorrowAmount = ({
195
191
  targetLeverage,
196
192
  priceCollToDebt,
197
193
  flashBorrowFee,
198
- borrowFee,
199
194
  }: {
200
195
  depositTokenAmount: Decimal;
201
196
  targetLeverage: Decimal;
202
197
  priceCollToDebt: Decimal;
203
198
  flashBorrowFee: Decimal;
204
- borrowFee: Decimal;
205
199
  }) => {
206
200
  const initialCollAmountInCollToken = depositTokenAmount;
207
201
 
@@ -210,8 +204,7 @@ export const calcBorrowAmount = ({
210
204
  const finalDebtAmountInDebtToken = finalDebtAmountInCollToken.mul(priceCollToDebt);
211
205
 
212
206
  const flashFeeFactor = new Decimal(1).add(flashBorrowFee);
213
- const borrowFeeFactor = new Decimal(1).add(borrowFee);
214
- const debtTokenToBorrow = finalDebtAmountInDebtToken.mul(flashFeeFactor).mul(borrowFeeFactor);
207
+ const debtTokenToBorrow = finalDebtAmountInDebtToken.mul(flashFeeFactor);
215
208
 
216
209
  return debtTokenToBorrow;
217
210
  };
@@ -281,7 +274,6 @@ export function calcWithdrawAmounts(params: WithdrawParams): WithdrawResult {
281
274
  priceCollToDebt: new Decimal(priceCollToDebt),
282
275
  targetLeverage: new Decimal(targetLeverage),
283
276
  flashBorrowFee: new Decimal(0),
284
- borrowFee: new Decimal(0),
285
277
  });
286
278
 
287
279
  const adjustDepositPosition = currentDepositPosition.minus(targetDeposit);
@@ -301,7 +293,6 @@ interface UseEstimateAdjustAmountsProps {
301
293
  totalDeposited: Decimal;
302
294
  totalBorrowed: Decimal;
303
295
  flashLoanFee: Decimal;
304
- borrowFee: Decimal;
305
296
  }
306
297
 
307
298
  /**
@@ -312,7 +303,7 @@ interface UseEstimateAdjustAmountsProps {
312
303
  */
313
304
  export const estimateAdjustMode = (
314
305
  priceCollToDebt: Decimal,
315
- { targetLeverage, totalDeposited, totalBorrowed, flashLoanFee, borrowFee }: UseEstimateAdjustAmountsProps
306
+ { targetLeverage, totalDeposited, totalBorrowed, flashLoanFee }: UseEstimateAdjustAmountsProps
316
307
  ) => {
317
308
  return calcAdjustAmounts({
318
309
  currentBorrowPosition: totalBorrowed,
@@ -320,7 +311,6 @@ export const estimateAdjustMode = (
320
311
  priceCollToDebt,
321
312
  targetLeverage,
322
313
  flashLoanFee,
323
- borrowFee,
324
314
  });
325
315
  };
326
316
 
@@ -330,7 +320,6 @@ export interface AdjustLeverageParams {
330
320
  currentDepositPosition: Decimal;
331
321
  priceCollToDebt: Decimal;
332
322
  flashLoanFee: Decimal;
333
- borrowFee: Decimal;
334
323
  }
335
324
 
336
325
  interface AdjustLeverageResult {
@@ -354,7 +343,6 @@ export function calcAdjustAmounts({
354
343
  currentDepositPosition,
355
344
  priceCollToDebt,
356
345
  flashLoanFee,
357
- borrowFee,
358
346
  }: AdjustLeverageParams): AdjustLeverageResult {
359
347
  const initialDeposit = currentDepositPosition.minus(currentBorrowPosition.div(priceCollToDebt));
360
348
  const targetDeposit = initialDeposit.mul(targetLeverage);
@@ -364,7 +352,6 @@ export function calcAdjustAmounts({
364
352
  priceCollToDebt: new Decimal(priceCollToDebt),
365
353
  targetLeverage: new Decimal(targetLeverage),
366
354
  flashBorrowFee: flashLoanFee,
367
- borrowFee,
368
355
  });
369
356
 
370
357
  const adjustDepositPosition = targetDeposit.minus(currentDepositPosition);
@@ -384,7 +371,6 @@ interface UseTransactionInfoStats {
384
371
  selectedTokenMint: PublicKey;
385
372
  collTokenMint: PublicKey;
386
373
  flashLoanFee: Decimal;
387
- borrowFee: Decimal;
388
374
  slippagePct?: Decimal;
389
375
  }
390
376
 
@@ -398,7 +384,6 @@ export const estimateDepositMode = ({
398
384
  selectedTokenMint,
399
385
  collTokenMint,
400
386
  flashLoanFee,
401
- borrowFee,
402
387
  slippagePct = new Decimal(0),
403
388
  }: UseTransactionInfoStats) => {
404
389
  const isDepositingCollToken = selectedTokenMint.equals(collTokenMint);
@@ -413,7 +398,6 @@ export const estimateDepositMode = ({
413
398
  targetLeverage: new Decimal(targetLeverage),
414
399
  priceCollToDebt: new Decimal(priceCollToDebt),
415
400
  flashBorrowFee: new Decimal(flashLoanFee),
416
- borrowFee: new Decimal(borrowFee),
417
401
  });
418
402
 
419
403
  const slippageFactor = new Decimal(1).add(slippagePct.div(new Decimal(100)));