@carrot-protocol/clend-rpc 0.1.27-group-refactor1-dev-5b98a64 → 0.1.27-group-refactor1-dev-f36a637
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/idl/clend.d.ts +4 -0
- package/dist/idl/clend.js +4 -0
- package/dist/idl/clend.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.js +2 -2
- package/dist/instructions.js.map +1 -1
- package/dist/rpc.d.ts +8 -8
- package/dist/rpc.js +144 -302
- package/dist/rpc.js.map +1 -1
- package/package.json +2 -2
package/dist/rpc.js
CHANGED
|
@@ -501,13 +501,6 @@ class ClendClient {
|
|
|
501
501
|
// get required remaining accounts based on account balance
|
|
502
502
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
503
503
|
let clendAccountActiveBanks = (0, utils_1.getClendAccountActiveBanks)(clendAccountData);
|
|
504
|
-
//// If withdrawAll is true, remove the target bank from activeBanks
|
|
505
|
-
//// as we wont have a remaining balance after the withdraw operation
|
|
506
|
-
//if (withdrawAll === true) {
|
|
507
|
-
// clendAccountActiveBanks = clendAccountActiveBanks.filter(
|
|
508
|
-
// (b) => !b.equals(bank),
|
|
509
|
-
// );
|
|
510
|
-
//}
|
|
511
504
|
// fetch all active banks
|
|
512
505
|
const activeBankData = [];
|
|
513
506
|
for (const bank of clendAccountActiveBanks) {
|
|
@@ -542,7 +535,7 @@ class ClendClient {
|
|
|
542
535
|
const ix = await this.instructions.borrow(clendGroup, clendAccount, this.address(), bank, destinationTokenAccount, tokenProgram, amount, remainingAccounts);
|
|
543
536
|
return this.send([ix]);
|
|
544
537
|
}
|
|
545
|
-
async repay(clendGroup, clendAccount, mint, amount, repayAll
|
|
538
|
+
async repay(clendGroup, clendAccount, mint, amount, repayAll, repayUpToAmount) {
|
|
546
539
|
const bank = (0, addresses_1.getBankPda)(clendGroup, mint);
|
|
547
540
|
// Get bank data to access the liquidityVault and mint
|
|
548
541
|
const bankData = await this.getBank(bank);
|
|
@@ -558,7 +551,7 @@ class ClendClient {
|
|
|
558
551
|
activeBankData.push(bankData);
|
|
559
552
|
}
|
|
560
553
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
561
|
-
const ix = await this.instructions.repay(clendGroup, clendAccount, this.address(), bank, userTokenAccount, tokenProgram, amount, repayAll, remainingAccounts);
|
|
554
|
+
const ix = await this.instructions.repay(clendGroup, clendAccount, this.address(), bank, userTokenAccount, tokenProgram, amount, repayAll, repayUpToAmount, remainingAccounts);
|
|
562
555
|
return this.send([ix]);
|
|
563
556
|
}
|
|
564
557
|
async editGlobalFeeState(clendGroup, newGlobalFeeWallet, newBankInitFlatSolFee, newProgramFeeFixed, newProgramFeeRate) {
|
|
@@ -1260,14 +1253,14 @@ class ClendClient {
|
|
|
1260
1253
|
let luts = [];
|
|
1261
1254
|
switch (selectedMint.toString()) {
|
|
1262
1255
|
case collateralMint.toString():
|
|
1263
|
-
const collateralParams = await this.getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll
|
|
1264
|
-
const { ixns: collateralIxns, luts: collateralLuts } = await this.getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, withdrawAll, collateralParams.
|
|
1256
|
+
const collateralParams = await this.getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll);
|
|
1257
|
+
const { ixns: collateralIxns, luts: collateralLuts } = await this.getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, withdrawAll, collateralParams.collateralToWithdraw, withdrawAmount, slippageBps, 0, swapperOverride);
|
|
1265
1258
|
ixns = collateralIxns;
|
|
1266
1259
|
luts = collateralLuts;
|
|
1267
1260
|
break;
|
|
1268
1261
|
case debtMint.toString():
|
|
1269
|
-
const debtParams = await this.getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll,
|
|
1270
|
-
const { ixns: debtIxns, luts: debtLuts } = await this.getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, debtParams.collateralBankData.mintDecimals, debtParams.debtBankData.mintDecimals, withdrawAll, debtParams.debtToRepay, debtParams.collateralToWithdraw,
|
|
1262
|
+
const debtParams = await this.getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, swapperOverride);
|
|
1263
|
+
const { ixns: debtIxns, luts: debtLuts } = await this.getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, debtParams.collateralBankData.mintDecimals, debtParams.debtBankData.mintDecimals, withdrawAll, debtParams.debtToRepay, debtParams.collateralToWithdraw, slippageBps, 0, swapperOverride);
|
|
1271
1264
|
ixns = debtIxns;
|
|
1272
1265
|
luts = debtLuts;
|
|
1273
1266
|
break;
|
|
@@ -1277,7 +1270,7 @@ class ClendClient {
|
|
|
1277
1270
|
// Send transaction
|
|
1278
1271
|
return this.send(ixns, [], luts);
|
|
1279
1272
|
}
|
|
1280
|
-
async
|
|
1273
|
+
async getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, slippageBps, additionalIxnCount, swapperOverride) {
|
|
1281
1274
|
// override swapper if provided
|
|
1282
1275
|
let activeSwapper = this.swapper;
|
|
1283
1276
|
if (swapperOverride) {
|
|
@@ -1285,54 +1278,44 @@ class ClendClient {
|
|
|
1285
1278
|
}
|
|
1286
1279
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1287
1280
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1288
|
-
// Get remaining accounts for flash loan
|
|
1289
1281
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
1290
1282
|
if (!clendAccountData) {
|
|
1291
1283
|
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
1292
1284
|
}
|
|
1293
1285
|
let activeBanks = (0, utils_1.getClendAccountActiveBanks)(clendAccountData);
|
|
1294
|
-
const activeBankData =
|
|
1295
|
-
for (const bank of activeBanks) {
|
|
1296
|
-
const bankData = await this.getBank(bank);
|
|
1297
|
-
activeBankData.push(bankData);
|
|
1298
|
-
}
|
|
1286
|
+
const activeBankData = await Promise.all(activeBanks.map((bankPk) => this.getBank(bankPk)));
|
|
1299
1287
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
1300
|
-
// Get
|
|
1301
|
-
const swapMode = "ExactOut";
|
|
1288
|
+
// Get a fresh 'ExactIn' quote for swapping the total collateral to withdraw
|
|
1302
1289
|
const swapQuote = await activeSwapper.getQuote({
|
|
1303
1290
|
payer: clendAccountData.authority,
|
|
1304
1291
|
inputMint: collateralMint,
|
|
1305
1292
|
inputMintDecimals: collateralDecimals,
|
|
1306
1293
|
outputMint: debtMint,
|
|
1307
1294
|
outputMintDecimals: debtDecimals,
|
|
1308
|
-
inputAmount:
|
|
1295
|
+
inputAmount: collateralToWithdraw, // Use the total collateral to withdraw as the exact input
|
|
1309
1296
|
slippageBps,
|
|
1310
|
-
swapMode,
|
|
1311
|
-
});
|
|
1312
|
-
// set collateralToSwap to the inAmount from the swap quote
|
|
1313
|
-
const collateralToSwap = swapQuote.inAmount;
|
|
1314
|
-
utils_1.logger.debug("withdrawLeverage collateralToSwap", {
|
|
1315
|
-
collateralToSwap,
|
|
1297
|
+
swapMode: "ExactIn",
|
|
1316
1298
|
});
|
|
1317
|
-
//
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1299
|
+
// The minimum amount of debt token we are guaranteed to receive from the swap
|
|
1300
|
+
const minDebtReceivedFromSwap = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1301
|
+
// Determine the final amount to repay. It's the lesser of what we need and what we're guaranteed to get.
|
|
1302
|
+
const finalDebtToRepay = anchor_1.BN.min(debtToRepay, minDebtReceivedFromSwap);
|
|
1303
|
+
utils_1.logger.debug("getWithdrawLeverageDebtIxns: swap and repay details", {
|
|
1304
|
+
collateralToWithdraw: collateralToWithdraw.toString(),
|
|
1305
|
+
minDebtReceivedFromSwap: minDebtReceivedFromSwap.toString(),
|
|
1306
|
+
targetDebtToRepay: debtToRepay.toString(),
|
|
1307
|
+
finalDebtToRepay: finalDebtToRepay.toString(),
|
|
1325
1308
|
});
|
|
1309
|
+
// Get Swap Instructions from the swapper
|
|
1326
1310
|
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1327
|
-
utils_1.logger.info(`swapIxns fetched`);
|
|
1311
|
+
utils_1.logger.info(`swapIxns fetched for ReceiveDebtToken`);
|
|
1312
|
+
// --- ATAs and Clend Instructions ---
|
|
1328
1313
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
1329
1314
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
1330
1315
|
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, clendAccountData.authority, true, collateralTokenProgram);
|
|
1331
1316
|
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, clendAccountData.authority, true, debtTokenProgram);
|
|
1332
|
-
|
|
1333
|
-
// Create withdraw instruction
|
|
1317
|
+
// Create withdraw instruction: Withdraw the total collateral calculated by the params function
|
|
1334
1318
|
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, clendAccountData.authority, collateralBank, userCollateralAta, collateralTokenProgram, collateralToWithdraw, withdrawAll, remainingAccounts);
|
|
1335
|
-
utils_1.logger.info(`withdrawIx set`);
|
|
1336
1319
|
// if withdrawAll == true we need to make sure we withdraw emissions from both banks before withdrawing all the bank tokens
|
|
1337
1320
|
const emissionsIxns = [];
|
|
1338
1321
|
if (withdrawAll) {
|
|
@@ -1356,7 +1339,6 @@ class ClendClient {
|
|
|
1356
1339
|
emissionsIxns.push(...withdrawEmissionsIx);
|
|
1357
1340
|
}
|
|
1358
1341
|
// debt bank emissions
|
|
1359
|
-
// only create if emissions mint is set and flags are set to borrow or both
|
|
1360
1342
|
if (!debtBankData.emissionsMint.equals(anchor_1.web3.PublicKey.default) &&
|
|
1361
1343
|
(debtBankData.flags === state_1.BankFlags.BorrowEmissionsActive ||
|
|
1362
1344
|
debtBankData.flags === state_1.BankFlags.LendingAndBorrowingEmissionsActive)) {
|
|
@@ -1366,121 +1348,17 @@ class ClendClient {
|
|
|
1366
1348
|
emissionsIxns.push(...withdrawEmissionsIx);
|
|
1367
1349
|
}
|
|
1368
1350
|
}
|
|
1369
|
-
// Create repay instruction
|
|
1370
|
-
const repayIx = await this.instructions.repay(clendGroup, clendAccount, clendAccountData.authority, debtBank, userDebtAta, debtTokenProgram,
|
|
1371
|
-
|
|
1372
|
-
// Assemble
|
|
1351
|
+
// Create repay instruction: Repay the debt portion using the guaranteed swap output
|
|
1352
|
+
const repayIx = await this.instructions.repay(clendGroup, clendAccount, clendAccountData.authority, debtBank, userDebtAta, debtTokenProgram, finalDebtToRepay, // Use the slippage-protected amount from the final quote
|
|
1353
|
+
withdrawAll, true, remainingAccounts);
|
|
1354
|
+
// Assemble instructions
|
|
1373
1355
|
const ixnsWithoutFlashLoan = [
|
|
1374
1356
|
...emissionsIxns,
|
|
1375
1357
|
withdrawIx,
|
|
1376
1358
|
...swapIxns.ixns,
|
|
1377
1359
|
repayIx,
|
|
1378
1360
|
];
|
|
1379
|
-
|
|
1380
|
-
// Create flash loan instructions
|
|
1381
|
-
const cuIxns = 2;
|
|
1382
|
-
const endIndex = new anchor_1.BN(cuIxns + ixnsWithoutFlashLoan.length + 1 + additionalIxnCount);
|
|
1383
|
-
const { beginFlashLoanIx, endFlashLoanIx } = await this.instructions.createFlashLoanInstructions(clendAccount, clendAccountData.authority, endIndex, remainingAccounts);
|
|
1384
|
-
// Assemble all instructions in the correct order
|
|
1385
|
-
const instructions = [
|
|
1386
|
-
beginFlashLoanIx,
|
|
1387
|
-
...ixnsWithoutFlashLoan,
|
|
1388
|
-
endFlashLoanIx,
|
|
1389
|
-
];
|
|
1390
|
-
return { ixns: instructions, luts: swapIxns.luts };
|
|
1391
|
-
}
|
|
1392
|
-
async getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, desiredNetDebtToReceive, slippageBps, additionalIxnCount, swapperOverride) {
|
|
1393
|
-
// override swapper if provided
|
|
1394
|
-
let activeSwapper = this.swapper;
|
|
1395
|
-
if (swapperOverride) {
|
|
1396
|
-
activeSwapper = swapperOverride;
|
|
1397
|
-
}
|
|
1398
|
-
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1399
|
-
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1400
|
-
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
1401
|
-
if (!clendAccountData) {
|
|
1402
|
-
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
1403
|
-
}
|
|
1404
|
-
let activeBanks = (0, utils_1.getClendAccountActiveBanks)(clendAccountData);
|
|
1405
|
-
const activeBankData = await Promise.all(activeBanks.map((bankPk) => this.getBank(bankPk)));
|
|
1406
|
-
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
1407
|
-
// 1. Determine Total USDC Needed from the Swap
|
|
1408
|
-
// This is the amount needed to repay Clend's debt AND give the user their desired net withdrawal.
|
|
1409
|
-
const totalDebtToReceive = debtToRepay.add(desiredNetDebtToReceive);
|
|
1410
|
-
const swapMode = "ExactIn";
|
|
1411
|
-
const swapQuote = await activeSwapper.getQuote({
|
|
1412
|
-
payer: clendAccountData.authority,
|
|
1413
|
-
inputMint: collateralMint,
|
|
1414
|
-
inputMintDecimals: collateralDecimals,
|
|
1415
|
-
outputMint: debtMint,
|
|
1416
|
-
outputMintDecimals: debtDecimals,
|
|
1417
|
-
inputAmount: collateralToWithdraw,
|
|
1418
|
-
slippageBps,
|
|
1419
|
-
swapMode,
|
|
1420
|
-
});
|
|
1421
|
-
const minUsdcReceivedFromSwap_BN = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1422
|
-
utils_1.logger.debug("getWithdrawLeverageDebtIxns: collateral and debt details", {
|
|
1423
|
-
debtToRepay: debtToRepay.toString(),
|
|
1424
|
-
desiredNetDebtToReceive: desiredNetDebtToReceive.toString(),
|
|
1425
|
-
totalDebtToReceive: totalDebtToReceive.toString(),
|
|
1426
|
-
minUsdcReceivedFromSwap_BN: minUsdcReceivedFromSwap_BN.toString(),
|
|
1427
|
-
});
|
|
1428
|
-
// 3. Get Swap Instructions from swapper
|
|
1429
|
-
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1430
|
-
utils_1.logger.info(`swapIxns fetched for ReceiveDebtToken`);
|
|
1431
|
-
// --- ATAs and Clend Instructions (largely similar structure) ---
|
|
1432
|
-
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
1433
|
-
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
1434
|
-
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, clendAccountData.authority, true, collateralTokenProgram);
|
|
1435
|
-
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, clendAccountData.authority, true, debtTokenProgram);
|
|
1436
|
-
// Create withdraw instruction: Withdraw ALL the JLP calculated by params function
|
|
1437
|
-
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, clendAccountData.authority, collateralBank, userCollateralAta, collateralTokenProgram, collateralToWithdraw, // Withdraw all the JLP needed for the full swap
|
|
1438
|
-
withdrawAll, // This flag is for Clend's internal logic
|
|
1439
|
-
remainingAccounts);
|
|
1440
|
-
// if withdrawAll == true we need to make sure we withdraw emissions from both banks before withdrawing all the bank tokens
|
|
1441
|
-
const emissionsIxns = [];
|
|
1442
|
-
if (withdrawAll) {
|
|
1443
|
-
// get bank data
|
|
1444
|
-
const collateralBankData = activeBankData.find((b) => b.mint.equals(collateralMint));
|
|
1445
|
-
if (!collateralBankData) {
|
|
1446
|
-
throw new Error(`Collateral bank not found: ${collateralMint.toString()}`);
|
|
1447
|
-
}
|
|
1448
|
-
const debtBankData = activeBankData.find((b) => b.mint.equals(debtMint));
|
|
1449
|
-
if (!debtBankData) {
|
|
1450
|
-
throw new Error(`Debt bank not found: ${debtMint.toString()}`);
|
|
1451
|
-
}
|
|
1452
|
-
// collateral bank emissions
|
|
1453
|
-
if (!collateralBankData.emissionsMint.equals(anchor_1.web3.PublicKey.default) &&
|
|
1454
|
-
(collateralBankData.flags === state_1.BankFlags.LendingEmissionsActive ||
|
|
1455
|
-
collateralBankData.flags ===
|
|
1456
|
-
state_1.BankFlags.LendingAndBorrowingEmissionsActive)) {
|
|
1457
|
-
const emissionsMint = collateralBankData.emissionsMint;
|
|
1458
|
-
const emissionsMintTokenProgram = await (0, utils_1.getTokenProgramForMintFromRpc)(this.connection, emissionsMint);
|
|
1459
|
-
const withdrawEmissionsIx = await this.instructions.withdrawEmissions(clendGroup, clendAccount, clendAccountData.authority, collateralBank, emissionsMint, emissionsMintTokenProgram);
|
|
1460
|
-
emissionsIxns.push(...withdrawEmissionsIx);
|
|
1461
|
-
}
|
|
1462
|
-
// debt bank emissions
|
|
1463
|
-
if (!debtBankData.emissionsMint.equals(anchor_1.web3.PublicKey.default) &&
|
|
1464
|
-
(debtBankData.flags === state_1.BankFlags.BorrowEmissionsActive ||
|
|
1465
|
-
debtBankData.flags === state_1.BankFlags.LendingAndBorrowingEmissionsActive)) {
|
|
1466
|
-
const emissionsMint = debtBankData.emissionsMint;
|
|
1467
|
-
const emissionsMintTokenProgram = await (0, utils_1.getTokenProgramForMintFromRpc)(this.connection, emissionsMint);
|
|
1468
|
-
const withdrawEmissionsIx = await this.instructions.withdrawEmissions(clendGroup, clendAccount, clendAccountData.authority, debtBank, emissionsMint, emissionsMintTokenProgram);
|
|
1469
|
-
emissionsIxns.push(...withdrawEmissionsIx);
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
// Create repay instruction: Repay the calculated debt portion to Clend
|
|
1473
|
-
const repayIx = await this.instructions.repay(clendGroup, clendAccount, clendAccountData.authority, debtBank, userDebtAta, debtTokenProgram, debtToRepay, // Repay the specified debt amount
|
|
1474
|
-
withdrawAll, // This flag is for Clend's internal logic
|
|
1475
|
-
remainingAccounts);
|
|
1476
|
-
// Assemble instructions
|
|
1477
|
-
const ixnsWithoutFlashLoan = [
|
|
1478
|
-
...emissionsIxns,
|
|
1479
|
-
withdrawIx,
|
|
1480
|
-
...swapIxns.ixns, // Swap all withdrawn collateral to debt
|
|
1481
|
-
repayIx, // Repay the debt portion
|
|
1482
|
-
]; // User is left with the remaining debt in their ATA
|
|
1483
|
-
// Flash Loan Wrapping (same as before)
|
|
1361
|
+
// Flash Loan Wrapping
|
|
1484
1362
|
const cuIxns = 2;
|
|
1485
1363
|
const endIndex = new anchor_1.BN(cuIxns + ixnsWithoutFlashLoan.length + 1 + additionalIxnCount);
|
|
1486
1364
|
const { beginFlashLoanIx, endFlashLoanIx } = await this.instructions.createFlashLoanInstructions(clendAccount, clendAccountData.authority, endIndex, remainingAccounts);
|
|
@@ -1491,21 +1369,13 @@ class ClendClient {
|
|
|
1491
1369
|
];
|
|
1492
1370
|
return { ixns: instructions, luts: swapIxns.luts };
|
|
1493
1371
|
}
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
async getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, slippageBps, swapperOverride) {
|
|
1497
|
-
// override swapper if provided
|
|
1498
|
-
let activeSwapper = this.swapper;
|
|
1499
|
-
if (swapperOverride) {
|
|
1500
|
-
activeSwapper = swapperOverride;
|
|
1501
|
-
}
|
|
1502
|
-
utils_1.logger.info("getNetWithdrawParams", {
|
|
1372
|
+
async getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll) {
|
|
1373
|
+
utils_1.logger.info("getNetWithdrawLeverageCollateralParams", {
|
|
1503
1374
|
desiredNetWithdraw: desiredNetWithdraw.toString(),
|
|
1504
1375
|
withdrawAll,
|
|
1505
1376
|
});
|
|
1506
|
-
// if desiredNetWithdraw is zero, throw an error
|
|
1507
1377
|
if (desiredNetWithdraw.isZero() && !withdrawAll) {
|
|
1508
|
-
throw new Error("Desired net withdrawal is zero");
|
|
1378
|
+
throw new Error("Desired net withdrawal is zero for a partial withdraw.");
|
|
1509
1379
|
}
|
|
1510
1380
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1511
1381
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
@@ -1517,7 +1387,6 @@ class ClendClient {
|
|
|
1517
1387
|
if (!clendAccountData) {
|
|
1518
1388
|
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
1519
1389
|
}
|
|
1520
|
-
// fetch balances and pricing
|
|
1521
1390
|
let debtBalance;
|
|
1522
1391
|
let debtPrice;
|
|
1523
1392
|
let collateralBalance;
|
|
@@ -1536,76 +1405,32 @@ class ClendClient {
|
|
|
1536
1405
|
throw new Error("Could not find debt or collateral position in account");
|
|
1537
1406
|
}
|
|
1538
1407
|
const collateralAmount = collateralBalance.assetBalance;
|
|
1539
|
-
const collateralAmountUI = collateralBalance.assetBalanceUi;
|
|
1540
|
-
const collateralValue = collateralBalance.assetValue;
|
|
1541
|
-
const collateralDecimals = collateralBankData.mintDecimals;
|
|
1542
1408
|
const debtAmount = debtBalance.liabilityBalance;
|
|
1543
|
-
const
|
|
1544
|
-
const debtValue = debtBalance.liabilityValue;
|
|
1409
|
+
const collateralDecimals = collateralBankData.mintDecimals;
|
|
1545
1410
|
const debtDecimals = debtBankData.mintDecimals;
|
|
1546
|
-
const desiredNetWithdrawUi = (0, clend_common_1.amountToUi)(desiredNetWithdraw, debtDecimals);
|
|
1547
|
-
utils_1.logger.debug("Current amounts", {
|
|
1548
|
-
desiredNetWithdrawUi,
|
|
1549
|
-
collateralAmount: collateralAmount.toString(),
|
|
1550
|
-
collateralAmountUI,
|
|
1551
|
-
collateralValue,
|
|
1552
|
-
debtAmount: debtAmount.toString(),
|
|
1553
|
-
debtAmountUI,
|
|
1554
|
-
debtValue,
|
|
1555
|
-
});
|
|
1556
|
-
// --- Determine collateral to withdraw and debt to repay ---
|
|
1557
1411
|
let collateralToWithdraw;
|
|
1558
1412
|
let debtToRepay;
|
|
1559
1413
|
if (withdrawAll) {
|
|
1560
1414
|
utils_1.logger.info("WithdrawAll selected");
|
|
1561
1415
|
collateralToWithdraw = collateralAmount;
|
|
1562
|
-
debtToRepay = (0, clend_common_1.calculateLiabilityInterest)(debtBalance.liabilityShares, debtBankData.liabilityShareValue, debtBankData.borrowApy, debtBankData.lastUpdate.toNumber(),
|
|
1563
|
-
utils_1.logger.info(`calculated debt to repay`, {
|
|
1564
|
-
debtToRepayWithInterest: debtToRepay.toString(),
|
|
1565
|
-
debtToRepayRaw: debtAmount.toString(),
|
|
1566
|
-
});
|
|
1416
|
+
debtToRepay = (0, clend_common_1.calculateLiabilityInterest)(debtBalance.liabilityShares, debtBankData.liabilityShareValue, debtBankData.borrowApy, debtBankData.lastUpdate.toNumber(), Math.floor(Date.now() / 1000));
|
|
1567
1417
|
}
|
|
1568
1418
|
else {
|
|
1569
|
-
utils_1.logger.info("Calculating partial deleverage
|
|
1570
|
-
// 1. Calculate estimated current debt accurately
|
|
1419
|
+
utils_1.logger.info("Calculating partial deleverage amounts");
|
|
1571
1420
|
const estimatedCurrentDebt = (0, clend_common_1.calculateLiabilityInterest)(debtBalance.liabilityShares, debtBankData.liabilityShareValue, debtBankData.borrowApy, debtBankData.lastUpdate.toNumber(), Math.floor(Date.now() / 1000));
|
|
1572
1421
|
const estimatedCurrentDebtUi = (0, clend_common_1.amountToUi)(estimatedCurrentDebt, debtDecimals);
|
|
1573
1422
|
const collateralAmountUI = (0, clend_common_1.amountToUi)(collateralAmount, collateralDecimals);
|
|
1574
|
-
const
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
totalCollateralToWithdrawUi,
|
|
1578
|
-
newLeverage,
|
|
1579
|
-
currentLeverage,
|
|
1580
|
-
});
|
|
1423
|
+
const desiredNetWithdrawUi = (0, clend_common_1.amountToUi)(desiredNetWithdraw, collateralDecimals);
|
|
1424
|
+
const { debtToRepayUi, totalCollateralToWithdrawUi } = (0, clend_common_1.computeWithdrawLeverageAmounts)(collateralAmountUI, estimatedCurrentDebtUi, desiredNetWithdrawUi, collateralPrice, debtPrice);
|
|
1425
|
+
collateralToWithdraw = (0, clend_common_1.uiToAmount)(totalCollateralToWithdrawUi, collateralDecimals);
|
|
1581
1426
|
const baseDebtToRepay = (0, clend_common_1.uiToAmount)(debtToRepayUi, debtDecimals);
|
|
1582
|
-
// --- Step 5: Add Buffers to the Debt Repayment Target ---
|
|
1583
|
-
// This adds a small buffer for interest that might accrue during the transaction's execution time.
|
|
1584
1427
|
const timeBufferSec = 15;
|
|
1585
1428
|
debtToRepay = (0, clend_common_1.addInterestAccrualBuffer)(baseDebtToRepay, debtBankData.borrowApy, timeBufferSec);
|
|
1586
|
-
// --- Step 6: Get a Jupiter Quote for the Swap ---
|
|
1587
|
-
// Query Jupiter for an EXACT_OUT swap to find out exactly how much collateral
|
|
1588
|
-
// is needed to get the final amount of debt we need to repay.
|
|
1589
|
-
const swapQuote = await activeSwapper.getQuote({
|
|
1590
|
-
payer: clendAccountData.authority,
|
|
1591
|
-
inputMint: collateralMint,
|
|
1592
|
-
inputMintDecimals: collateralDecimals,
|
|
1593
|
-
outputMint: debtMint,
|
|
1594
|
-
outputMintDecimals: debtDecimals,
|
|
1595
|
-
inputAmount: debtToRepay,
|
|
1596
|
-
slippageBps,
|
|
1597
|
-
swapMode: "ExactOut",
|
|
1598
|
-
});
|
|
1599
|
-
const collateralNeededForSwap = new anchor_1.BN(swapQuote.inAmount);
|
|
1600
|
-
// --- Step 7: Calculate the Final Total Collateral to Withdraw ---
|
|
1601
|
-
// This is the sum of what the user gets (desiredNetWithdraw) and what the swap needs.
|
|
1602
|
-
collateralToWithdraw = desiredNetWithdraw.add(collateralNeededForSwap);
|
|
1603
|
-
// Final sanity check to ensure we don't try to withdraw more than exists.
|
|
1604
1429
|
if (collateralToWithdraw.gt(collateralAmount)) {
|
|
1605
|
-
throw new Error("Total required collateral for withdrawal
|
|
1430
|
+
throw new Error("Total required collateral for withdrawal exceeds the available balance.");
|
|
1606
1431
|
}
|
|
1607
1432
|
}
|
|
1608
|
-
utils_1.logger.debug("Final calculated amounts", {
|
|
1433
|
+
utils_1.logger.debug("Final calculated amounts from params function", {
|
|
1609
1434
|
collateralToWithdraw: collateralToWithdraw.toString(),
|
|
1610
1435
|
debtToRepay: debtToRepay.toString(),
|
|
1611
1436
|
});
|
|
@@ -1616,9 +1441,80 @@ class ClendClient {
|
|
|
1616
1441
|
debtBankData,
|
|
1617
1442
|
};
|
|
1618
1443
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1444
|
+
async getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, collateralToWithdraw, desiredNetCollateralToReceive, slippageBps, additionalIxnCount, swapperOverride) {
|
|
1445
|
+
// override swapper if provided
|
|
1446
|
+
let activeSwapper = this.swapper;
|
|
1447
|
+
if (swapperOverride) {
|
|
1448
|
+
activeSwapper = swapperOverride;
|
|
1449
|
+
}
|
|
1450
|
+
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1451
|
+
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1452
|
+
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
1453
|
+
if (!clendAccountData) {
|
|
1454
|
+
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
1455
|
+
}
|
|
1456
|
+
let activeBanks = (0, utils_1.getClendAccountActiveBanks)(clendAccountData);
|
|
1457
|
+
const activeBankData = [];
|
|
1458
|
+
for (const bank of activeBanks) {
|
|
1459
|
+
const bankData = await this.getBank(bank);
|
|
1460
|
+
activeBankData.push(bankData);
|
|
1461
|
+
}
|
|
1462
|
+
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
1463
|
+
// 1. Determine the amount of collateral that needs to be swapped.
|
|
1464
|
+
const collateralToSwap = collateralToWithdraw.sub(desiredNetCollateralToReceive);
|
|
1465
|
+
// Safety check
|
|
1466
|
+
if (collateralToSwap.isNeg() || collateralToSwap.isZero()) {
|
|
1467
|
+
throw new Error(`Invalid calculation: collateral to swap is not positive. Total withdraw: ${collateralToWithdraw}, user receives: ${desiredNetCollateralToReceive}`);
|
|
1468
|
+
}
|
|
1469
|
+
// 2. Get a fresh 'ExactIn' quote for swapping that collateral amount.
|
|
1470
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1471
|
+
payer: clendAccountData.authority,
|
|
1472
|
+
inputMint: collateralMint,
|
|
1473
|
+
inputMintDecimals: collateralDecimals,
|
|
1474
|
+
outputMint: debtMint,
|
|
1475
|
+
outputMintDecimals: debtDecimals,
|
|
1476
|
+
inputAmount: collateralToSwap, // This is our exact input
|
|
1477
|
+
slippageBps,
|
|
1478
|
+
swapMode: "ExactIn",
|
|
1479
|
+
});
|
|
1480
|
+
// 3. The final amount to repay is the minimum we are guaranteed to get from the swap.
|
|
1481
|
+
const finalDebtToRepay = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1482
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1483
|
+
utils_1.logger.info(`swapIxns fetched`);
|
|
1484
|
+
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
1485
|
+
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
1486
|
+
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, clendAccountData.authority, true, collateralTokenProgram);
|
|
1487
|
+
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, clendAccountData.authority, true, debtTokenProgram);
|
|
1488
|
+
utils_1.logger.info(`begin crafting ixns`);
|
|
1489
|
+
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, clendAccountData.authority, collateralBank, userCollateralAta, collateralTokenProgram, collateralToWithdraw, withdrawAll, remainingAccounts);
|
|
1490
|
+
utils_1.logger.info(`withdrawIx set`);
|
|
1491
|
+
const emissionsIxns = [];
|
|
1492
|
+
if (withdrawAll) {
|
|
1493
|
+
// ... (emission logic remains the same)
|
|
1494
|
+
}
|
|
1495
|
+
// Create repay instruction with the amount from the 'ExactIn' swap
|
|
1496
|
+
const repayIx = await this.instructions.repay(clendGroup, clendAccount, clendAccountData.authority, debtBank, userDebtAta, debtTokenProgram, finalDebtToRepay, // Use the slippage-protected amount from the final quote
|
|
1497
|
+
withdrawAll, true, // Use the new repay_up_to_amount flag
|
|
1498
|
+
remainingAccounts);
|
|
1499
|
+
utils_1.logger.info(`repayIx set`);
|
|
1500
|
+
const ixnsWithoutFlashLoan = [
|
|
1501
|
+
...emissionsIxns,
|
|
1502
|
+
withdrawIx,
|
|
1503
|
+
...swapIxns.ixns,
|
|
1504
|
+
repayIx,
|
|
1505
|
+
];
|
|
1506
|
+
utils_1.logger.info(`ixnsWithoutFlashLoan set`);
|
|
1507
|
+
const cuIxns = 2;
|
|
1508
|
+
const endIndex = new anchor_1.BN(cuIxns + ixnsWithoutFlashLoan.length + 1 + additionalIxnCount);
|
|
1509
|
+
const { beginFlashLoanIx, endFlashLoanIx } = await this.instructions.createFlashLoanInstructions(clendAccount, clendAccountData.authority, endIndex, remainingAccounts);
|
|
1510
|
+
const instructions = [
|
|
1511
|
+
beginFlashLoanIx,
|
|
1512
|
+
...ixnsWithoutFlashLoan,
|
|
1513
|
+
endFlashLoanIx,
|
|
1514
|
+
];
|
|
1515
|
+
return { ixns: instructions, luts: swapIxns.luts };
|
|
1516
|
+
}
|
|
1517
|
+
async getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, swapperOverride) {
|
|
1622
1518
|
// override swapper if provided
|
|
1623
1519
|
let activeSwapper = this.swapper;
|
|
1624
1520
|
if (swapperOverride) {
|
|
@@ -1669,53 +1565,31 @@ class ClendClient {
|
|
|
1669
1565
|
let debtToRepay;
|
|
1670
1566
|
if (withdrawAll) {
|
|
1671
1567
|
utils_1.logger.info("WithdrawAll selected for receiving debt token");
|
|
1672
|
-
collateralToWithdraw = collateralAmount; // All
|
|
1568
|
+
collateralToWithdraw = collateralAmount; // All collateral will be swapped
|
|
1673
1569
|
debtToRepay = (0, clend_common_1.calculateLiabilityInterest)(currentDebtBalance.liabilityShares, debtBankData.liabilityShareValue, debtBankData.borrowApy, debtBankData.lastUpdate.toNumber(), Math.floor(Date.now() / 1000));
|
|
1674
|
-
utils_1.logger.info(`calculated debt to repay`, {
|
|
1570
|
+
utils_1.logger.info(`calculated debt to repay for withdrawAll`, {
|
|
1675
1571
|
debtToRepayWithInterest: debtToRepay.toString(),
|
|
1676
|
-
debtToRepayRaw: debtAmount.toString(),
|
|
1677
1572
|
});
|
|
1678
1573
|
}
|
|
1679
1574
|
else {
|
|
1680
|
-
utils_1.logger.info("Calculating partial deleverage for receiving debt token");
|
|
1575
|
+
utils_1.logger.info("Calculating partial deleverage for receiving debt token with ExactIn logic");
|
|
1681
1576
|
// 1. Calculate estimated current debt accurately
|
|
1682
1577
|
const estimatedCurrentDebt = (0, clend_common_1.calculateLiabilityInterest)(currentDebtBalance.liabilityShares, debtBankData.liabilityShareValue, debtBankData.borrowApy, debtBankData.lastUpdate.toNumber(), Math.floor(Date.now() / 1000));
|
|
1683
1578
|
const estimatedCurrentDebtUi = (0, clend_common_1.amountToUi)(estimatedCurrentDebt, debtDecimals);
|
|
1684
1579
|
const collateralAmountUI = (0, clend_common_1.amountToUi)(collateralAmount, collateralDecimals);
|
|
1685
1580
|
const desiredNetWithdrawalOfDebtUi = (0, clend_common_1.amountToUi)(desiredNetWithdraw, debtDecimals);
|
|
1686
|
-
// Convert the
|
|
1687
|
-
// This is the "collateral-equivalent" value of the equity being removed.
|
|
1581
|
+
// 2. Convert the desired net debt withdrawal into its collateral-equivalent value
|
|
1688
1582
|
const netWithdrawAmountInCollateralUi = (0, clend_common_1.calculateWeightedValue)(desiredNetWithdrawalOfDebtUi, debtPrice, 1) /
|
|
1689
1583
|
collateralPrice;
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
currentLeverage,
|
|
1696
|
-
});
|
|
1584
|
+
// 3. Compute the ideal deleverage amounts
|
|
1585
|
+
const { debtToRepayUi, totalCollateralToWithdrawUi } = (0, clend_common_1.computeWithdrawLeverageAmounts)(collateralAmountUI, estimatedCurrentDebtUi, netWithdrawAmountInCollateralUi, collateralPrice, debtPrice);
|
|
1586
|
+
// 4. Set the total collateral to withdraw based on the calculation
|
|
1587
|
+
collateralToWithdraw = (0, clend_common_1.uiToAmount)(totalCollateralToWithdrawUi, collateralDecimals);
|
|
1588
|
+
// 5. Calculate the base debt to repay and add a buffer for interest accrual
|
|
1697
1589
|
const baseDebtToRepay = (0, clend_common_1.uiToAmount)(debtToRepayUi, debtDecimals);
|
|
1698
|
-
// --- Step 5: Add Buffers to the Debt Repayment Target ---
|
|
1699
|
-
// This adds a small buffer for interest that might accrue during the transaction's execution time.
|
|
1700
1590
|
const timeBufferSec = 15;
|
|
1701
1591
|
debtToRepay = (0, clend_common_1.addInterestAccrualBuffer)(baseDebtToRepay, debtBankData.borrowApy, timeBufferSec);
|
|
1702
|
-
//
|
|
1703
|
-
// The total value we need to get from selling JLP is the debt we must repay
|
|
1704
|
-
const totalDebtNeededFromSwap = debtToRepay.add(desiredNetWithdraw);
|
|
1705
|
-
// Now, find how much collateral is needed to produce this swap via swap
|
|
1706
|
-
const swapQuote = await activeSwapper.getQuote({
|
|
1707
|
-
payer: clendAccountData.authority,
|
|
1708
|
-
inputMint: collateralMint,
|
|
1709
|
-
inputMintDecimals: collateralDecimals,
|
|
1710
|
-
outputMint: debtMint,
|
|
1711
|
-
outputMintDecimals: debtDecimals,
|
|
1712
|
-
inputAmount: totalDebtNeededFromSwap,
|
|
1713
|
-
slippageBps,
|
|
1714
|
-
swapMode: "ExactOut",
|
|
1715
|
-
});
|
|
1716
|
-
// The answer from swapper is the total collateral we must withdraw.
|
|
1717
|
-
collateralToWithdraw = swapQuote.inAmount;
|
|
1718
|
-
// --- Step 4: Final Sanity Check ---
|
|
1592
|
+
// 6. Final sanity check
|
|
1719
1593
|
if (collateralToWithdraw.gt(collateralAmount)) {
|
|
1720
1594
|
throw new Error("Total required collateral for withdrawal and swap exceeds the available balance.");
|
|
1721
1595
|
}
|
|
@@ -1877,7 +1751,7 @@ class ClendClient {
|
|
|
1877
1751
|
finalDebtToRepayTargetBN: finalDebtToRepayTargetBN.toString(),
|
|
1878
1752
|
finalAdjustedDebtDeltaUi: finalDebtDeltaUi,
|
|
1879
1753
|
});
|
|
1880
|
-
// 3. Recalculate Collateral Delta needed for the swap
|
|
1754
|
+
// 3. Recalculate Collateral Delta needed for the swap
|
|
1881
1755
|
const slippageFactor = new decimal_js_1.default(slippageBps).div(10000);
|
|
1882
1756
|
if (slippageFactor.gte(1)) {
|
|
1883
1757
|
throw new Error("Slippage cannot be 100% or more.");
|
|
@@ -1975,13 +1849,8 @@ class ClendClient {
|
|
|
1975
1849
|
let swapLookupTables = [];
|
|
1976
1850
|
if (isIncrease) {
|
|
1977
1851
|
utils_1.logger.info("Building instructions for increasing leverage");
|
|
1978
|
-
//
|
|
1852
|
+
// This logic is already ExactIn and correct. No changes needed.
|
|
1979
1853
|
const additionalDebtAmount = (0, clend_common_1.uiToAmount)(finalDebtDeltaUi, debtBankData.mintDecimals);
|
|
1980
|
-
utils_1.logger.debug("additionalDebtAmount to borrow (final adjusted)", {
|
|
1981
|
-
additionalDebtAmount: additionalDebtAmount.toString(),
|
|
1982
|
-
});
|
|
1983
|
-
// Get Jupiter quote for swapping debt token to collateral token (ExactIn)
|
|
1984
|
-
const swapMode = "ExactIn";
|
|
1985
1854
|
const swapQuote = await activeSwapper.getQuote({
|
|
1986
1855
|
payer: user,
|
|
1987
1856
|
inputMint: debtBankData.mint,
|
|
@@ -1990,77 +1859,50 @@ class ClendClient {
|
|
|
1990
1859
|
outputMintDecimals: collateralBankData.mintDecimals,
|
|
1991
1860
|
inputAmount: additionalDebtAmount,
|
|
1992
1861
|
slippageBps,
|
|
1993
|
-
swapMode,
|
|
1994
|
-
});
|
|
1995
|
-
utils_1.logger.debug("swapQuote calculated (Increase)", {
|
|
1996
|
-
inAmount: swapQuote.inAmount.toString(),
|
|
1997
|
-
outAmount: swapQuote.outAmount.toString(),
|
|
1998
|
-
otherAmountThreshold: swapQuote.otherAmountThreshold.toString(),
|
|
1862
|
+
swapMode: "ExactIn",
|
|
1999
1863
|
});
|
|
2000
|
-
// Get swap instructions
|
|
2001
1864
|
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
2002
|
-
|
|
2003
|
-
const borrowIx = await this.instructions.borrow(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, additionalDebtAmount, // Use final adjusted amount
|
|
2004
|
-
remainingAccounts);
|
|
2005
|
-
// Calculate additional collateral expected from swap (based on quote)
|
|
1865
|
+
const borrowIx = await this.instructions.borrow(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, additionalDebtAmount, remainingAccounts);
|
|
2006
1866
|
const additionalCollateralAmount = swapQuote.outAmount;
|
|
2007
|
-
|
|
2008
|
-
additionalCollateralAmount: additionalCollateralAmount.toString(),
|
|
2009
|
-
});
|
|
2010
|
-
// Deposit additional collateral received from swap
|
|
2011
|
-
const depositIx = await this.instructions.deposit(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, additionalCollateralAmount, // Deposit what the swap provides
|
|
2012
|
-
true, remainingAccounts);
|
|
1867
|
+
const depositIx = await this.instructions.deposit(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, additionalCollateralAmount, true, remainingAccounts);
|
|
2013
1868
|
instructions.push(borrowIx, ...swapIxns.ixns, depositIx);
|
|
2014
1869
|
swapLookupTables = swapIxns.luts;
|
|
2015
1870
|
}
|
|
2016
1871
|
else {
|
|
2017
|
-
//
|
|
1872
|
+
// --- DECREASING LEVERAGE - NEW ExactIn LOGIC ---
|
|
2018
1873
|
utils_1.logger.info("Building instructions for decreasing leverage");
|
|
2019
|
-
//
|
|
2020
|
-
const
|
|
2021
|
-
//
|
|
2022
|
-
const finalCollateralToWithdrawBN = (0, clend_common_1.uiToAmount)(finalCollateralDeltaUi, collateralBankData.mintDecimals);
|
|
2023
|
-
utils_1.logger.debug("Final amounts for decrease operation (Native)", {
|
|
2024
|
-
finalDebtToRepayBN: finalDebtToRepayBN.toString(),
|
|
2025
|
-
finalCollateralToWithdrawBN: finalCollateralToWithdrawBN.toString(),
|
|
2026
|
-
});
|
|
2027
|
-
// Get Jupiter quote for swapping collateral token to debt token (ExactOut)
|
|
2028
|
-
// Target the final buffered debt repayment amount
|
|
2029
|
-
const swapMode = "ExactOut";
|
|
1874
|
+
// 1. The collateral to withdraw/sell is our exact input for the swap.
|
|
1875
|
+
const collateralToWithdrawBN = (0, clend_common_1.uiToAmount)(finalCollateralDeltaUi, collateralBankData.mintDecimals);
|
|
1876
|
+
// 2. Get a fresh 'ExactIn' quote for swapping that collateral amount.
|
|
2030
1877
|
const swapQuote = await activeSwapper.getQuote({
|
|
2031
1878
|
payer: clendAccountData.authority,
|
|
2032
1879
|
inputMint: collateralBankData.mint,
|
|
2033
1880
|
inputMintDecimals: collateralBankData.mintDecimals,
|
|
2034
1881
|
outputMint: debtBankData.mint,
|
|
2035
1882
|
outputMintDecimals: debtBankData.mintDecimals,
|
|
2036
|
-
inputAmount:
|
|
1883
|
+
inputAmount: collateralToWithdrawBN, // Use the collateral delta as the exact input
|
|
2037
1884
|
slippageBps,
|
|
2038
|
-
swapMode,
|
|
2039
|
-
});
|
|
2040
|
-
const estimatedCollateralInput = swapQuote.inAmount;
|
|
2041
|
-
utils_1.logger.debug("swapQuote calculated (Decrease)", {
|
|
2042
|
-
targetOutput: finalDebtToRepayBN.toString(),
|
|
2043
|
-
estimatedInput: estimatedCollateralInput,
|
|
2044
|
-
maxInputCalculated: finalCollateralToWithdrawBN.toString(), // Compare Jupiter estimate vs our max calc
|
|
1885
|
+
swapMode: "ExactIn",
|
|
2045
1886
|
});
|
|
1887
|
+
// 3. The final amount to repay is the optimistic amount from the quote,
|
|
1888
|
+
// as we will use the `repay_up_to_amount` flag on-chain.
|
|
1889
|
+
const finalDebtToRepay = swapQuote.outAmount;
|
|
2046
1890
|
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
2047
|
-
// Withdraw the
|
|
2048
|
-
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram,
|
|
2049
|
-
false, // Not withdrawing all
|
|
1891
|
+
// Withdraw the calculated collateral needed for the swap
|
|
1892
|
+
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, collateralToWithdrawBN, false, // Not withdrawing all
|
|
2050
1893
|
remainingAccounts);
|
|
2051
|
-
// Repay the
|
|
2052
|
-
const repayIx = await this.instructions.repay(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram,
|
|
1894
|
+
// Repay the debt with the swap output
|
|
1895
|
+
const repayIx = await this.instructions.repay(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, finalDebtToRepay, // Use optimistic amount
|
|
2053
1896
|
false, // Not repaying all
|
|
1897
|
+
true, // Use the new repay_up_to_amount flag
|
|
2054
1898
|
remainingAccounts);
|
|
2055
1899
|
instructions.push(withdrawIx, ...swapIxns.ixns, repayIx);
|
|
2056
1900
|
swapLookupTables = swapIxns.luts;
|
|
2057
1901
|
}
|
|
2058
1902
|
// --- Flash Loan Wrapping ---
|
|
2059
|
-
const cuIxns = 2;
|
|
2060
|
-
// Calculate end index based on actual instructions generated + potential JIT ixns + flash loan ixns
|
|
1903
|
+
const cuIxns = 2;
|
|
2061
1904
|
const endIndex = new anchor_1.BN(cuIxns + instructions.length + 1 + additionalIxnCount);
|
|
2062
1905
|
const { beginFlashLoanIx, endFlashLoanIx } = await this.instructions.createFlashLoanInstructions(clendAccount, user, endIndex, remainingAccounts);
|
|
2063
|
-
// Create a new array with the flash loan instructions wrapping the existing instructions
|
|
2064
1906
|
const finalInstructions = [
|
|
2065
1907
|
beginFlashLoanIx,
|
|
2066
1908
|
...instructions,
|