@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.
- package/dist/classes/action.d.ts +23 -23
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +122 -195
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/index.d.ts +1 -0
- package/dist/classes/index.d.ts.map +1 -1
- package/dist/classes/index.js +1 -0
- package/dist/classes/index.js.map +1 -1
- package/dist/classes/manager.d.ts +6 -1
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +16 -1
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +3 -3
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +30 -16
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/obligation.d.ts +2 -0
- package/dist/classes/obligation.d.ts.map +1 -1
- package/dist/classes/obligation.js +5 -0
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/vault.js +1 -1
- package/dist/classes/vault.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.d.ts +4 -4
- package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.js +10 -8
- package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
- package/dist/lending_operations/swap_collateral_operations.d.ts +2 -2
- package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/swap_collateral_operations.js +11 -6
- package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
- package/dist/leverage/calcs.d.ts +5 -10
- package/dist/leverage/calcs.d.ts.map +1 -1
- package/dist/leverage/calcs.js +6 -13
- package/dist/leverage/calcs.js.map +1 -1
- package/dist/leverage/operations.d.ts +9 -7
- package/dist/leverage/operations.d.ts.map +1 -1
- package/dist/leverage/operations.js +78 -72
- package/dist/leverage/operations.js.map +1 -1
- package/dist/leverage/types.d.ts +4 -4
- package/dist/leverage/types.d.ts.map +1 -1
- package/dist/utils/ObligationType.d.ts +1 -1
- package/dist/utils/ObligationType.d.ts.map +1 -1
- package/dist/utils/managerTypes.d.ts.map +1 -1
- package/dist/utils/managerTypes.js +7 -52
- package/dist/utils/managerTypes.js.map +1 -1
- package/dist/utils/oracle.d.ts +3 -3
- package/dist/utils/oracle.d.ts.map +1 -1
- package/dist/utils/oracle.js +4 -3
- package/dist/utils/oracle.js.map +1 -1
- package/package.json +2 -2
- package/src/classes/action.ts +143 -211
- package/src/classes/index.ts +1 -0
- package/src/classes/manager.ts +32 -1
- package/src/classes/market.ts +34 -25
- package/src/classes/obligation.ts +6 -0
- package/src/classes/vault.ts +1 -1
- package/src/client.ts +8 -3
- package/src/lending_operations/repay_with_collateral_operations.ts +15 -11
- package/src/lending_operations/swap_collateral_operations.ts +19 -7
- package/src/leverage/calcs.ts +2 -18
- package/src/leverage/operations.ts +114 -72
- package/src/leverage/types.ts +4 -4
- package/src/utils/ObligationType.ts +1 -1
- package/src/utils/managerTypes.ts +10 -52
- package/src/utils/oracle.ts +7 -6
package/src/classes/index.ts
CHANGED
package/src/classes/manager.ts
CHANGED
|
@@ -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
|
|
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
|
package/src/classes/market.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
+
}
|
package/src/classes/vault.ts
CHANGED
|
@@ -301,7 +301,7 @@ export class KaminoVaultClient {
|
|
|
301
301
|
ctokenVault: cTokenVault,
|
|
302
302
|
systemProgram: SystemProgram.programId,
|
|
303
303
|
rent: SYSVAR_RENT_PUBKEY,
|
|
304
|
-
reserveCollateralTokenProgram:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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...
|
package/src/leverage/calcs.ts
CHANGED
|
@@ -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
|
|
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
|
|
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)));
|