@carrot-protocol/clend-rpc 0.1.26 → 0.1.27-group-refactor1-dev-5488543
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 -1
- package/dist/idl/clend.js +4 -1
- package/dist/idl/clend.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +4 -3
- package/dist/instructions.js +31 -4
- package/dist/instructions.js.map +1 -1
- package/dist/rpc.d.ts +25 -34
- package/dist/rpc.js +272 -160
- package/dist/rpc.js.map +1 -1
- package/dist/state.d.ts +16 -1
- package/dist/state.js +11 -2
- package/dist/state.js.map +1 -1
- package/dist/swapper/index.d.ts +3 -0
- package/dist/swapper/index.js +8 -0
- package/dist/swapper/index.js.map +1 -0
- package/dist/swapper/interface.d.ts +58 -0
- package/dist/swapper/interface.js +3 -0
- package/dist/swapper/interface.js.map +1 -0
- package/dist/swapper/jupiterSwapper.d.ts +15 -0
- package/dist/swapper/jupiterSwapper.js +85 -0
- package/dist/swapper/jupiterSwapper.js.map +1 -0
- package/dist/swapper/mockJupiterSwapper.d.ts +19 -0
- package/dist/swapper/mockJupiterSwapper.js +89 -0
- package/dist/swapper/mockJupiterSwapper.js.map +1 -0
- package/dist/utils.d.ts +29 -0
- package/dist/utils.js +67 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/dist/jupiterUtils.d.ts +0 -65
- package/dist/jupiterUtils.js +0 -174
- package/dist/jupiterUtils.js.map +0 -1
- package/dist/mockJupiterUtils.d.ts +0 -54
- package/dist/mockJupiterUtils.js +0 -75
- package/dist/mockJupiterUtils.js.map +0 -1
package/dist/rpc.js
CHANGED
|
@@ -12,13 +12,12 @@ const utils_1 = require("./utils");
|
|
|
12
12
|
const addresses_1 = require("./addresses");
|
|
13
13
|
const state_1 = require("./state");
|
|
14
14
|
const clend_common_1 = require("@carrot-protocol/clend-common");
|
|
15
|
-
const
|
|
16
|
-
const api_1 = require("@jup-ag/api");
|
|
15
|
+
const swapper_1 = require("./swapper");
|
|
17
16
|
const pyth_solana_receiver_1 = require("@pythnetwork/pyth-solana-receiver");
|
|
18
17
|
const events_1 = require("./events");
|
|
19
18
|
const marginfi_1 = require("./integrations/marginfi");
|
|
20
19
|
class ClendClient {
|
|
21
|
-
constructor(connection, wallet, skipPreflight, cuFeeInMicroLamports,
|
|
20
|
+
constructor(connection, wallet, skipPreflight, cuFeeInMicroLamports, defaultSwapper, dryRun, mintOracleMapping) {
|
|
22
21
|
this.provider = new anchor_1.AnchorProvider(connection, wallet, {
|
|
23
22
|
commitment: "processed",
|
|
24
23
|
skipPreflight,
|
|
@@ -26,7 +25,7 @@ class ClendClient {
|
|
|
26
25
|
this.connection = connection;
|
|
27
26
|
this.instructions = new instructions_1.Instructions(this.provider);
|
|
28
27
|
this.events = new events_1.ClendEvents(connection);
|
|
29
|
-
this.
|
|
28
|
+
this.swapper = defaultSwapper || new swapper_1.JupiterSwapper();
|
|
30
29
|
this.dryRun = dryRun || false;
|
|
31
30
|
this.cuFeeInMicroLamports = cuFeeInMicroLamports;
|
|
32
31
|
this.mintOracleMapping = mintOracleMapping || state_1.DEFAULT_ORACLE_MAP;
|
|
@@ -34,16 +33,25 @@ class ClendClient {
|
|
|
34
33
|
address() {
|
|
35
34
|
return this.provider.wallet.publicKey;
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
// determine type of oracle then fetch price from mint
|
|
37
|
+
// TODO: do it better than this hack
|
|
38
|
+
async getOraclePrice(mint) {
|
|
39
|
+
try {
|
|
40
|
+
return await this.getPythOraclePrice(mint);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
try {
|
|
44
|
+
return await this.getSBOraclePrice(mint);
|
|
45
|
+
}
|
|
46
|
+
catch (sbError) {
|
|
47
|
+
throw sbError;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
/**
|
|
44
52
|
* Get pyth oracle price for a token
|
|
45
53
|
*/
|
|
46
|
-
async
|
|
54
|
+
async getPythOraclePrice(mint) {
|
|
47
55
|
const oracle = this.getOracle(mint);
|
|
48
56
|
// get oracle account info
|
|
49
57
|
const oracleAccountInfo = await this.connection.getAccountInfo(oracle, {
|
|
@@ -62,9 +70,34 @@ class ClendClient {
|
|
|
62
70
|
// get ema price
|
|
63
71
|
const emaPrice = new anchor_1.BN(oracleData.priceMessage.emaPrice);
|
|
64
72
|
// return price
|
|
65
|
-
return (emaPrice.toNumber()
|
|
66
|
-
Math.pow(10, Number(oracleData.priceMessage.exponent)));
|
|
73
|
+
return (0, utils_1.calculatePriceUi)(emaPrice.toNumber(), oracleData.priceMessage.exponent);
|
|
67
74
|
}
|
|
75
|
+
async getSBOraclePrice(mint) {
|
|
76
|
+
const oracle = this.getOracle(mint);
|
|
77
|
+
// Fetch the raw account info.
|
|
78
|
+
const feedAccountInfo = await this.connection.getAccountInfo(oracle, "processed");
|
|
79
|
+
if (feedAccountInfo === null) {
|
|
80
|
+
throw new Error(`Feed account ${oracle.toString()} not found.`);
|
|
81
|
+
}
|
|
82
|
+
// Use our manual parser instead of the Anchor coder.
|
|
83
|
+
const pullFeedAccountData = (0, utils_1.parsePullFeedAccountData)(feedAccountInfo.data);
|
|
84
|
+
if (!pullFeedAccountData ||
|
|
85
|
+
!pullFeedAccountData.submissions ||
|
|
86
|
+
pullFeedAccountData.submissions.length === 0) {
|
|
87
|
+
throw new Error(`No valid submissions found for feed ${oracle.toString()}.`);
|
|
88
|
+
}
|
|
89
|
+
// The latest submission will be the first element after sorting.
|
|
90
|
+
const latestSubmission = pullFeedAccountData.submissions[0];
|
|
91
|
+
// The 'value' is a BN (BigNumber), so we convert it to a standard JavaScript number.
|
|
92
|
+
// Be aware of potential precision loss if the number is larger than Number.MAX_SAFE_INTEGER.
|
|
93
|
+
const price = new decimal_js_1.default(latestSubmission.value.toString());
|
|
94
|
+
// The exponent for Switchboard v2/v3 feeds is typically -18, but you should
|
|
95
|
+
// confirm this for the specific feed you are using.
|
|
96
|
+
const exponent = -18;
|
|
97
|
+
const priceDecimal = (0, utils_1.calculatePriceUiDecimal)(price, exponent);
|
|
98
|
+
return priceDecimal;
|
|
99
|
+
}
|
|
100
|
+
// find oracle for a mint from in memory cache
|
|
68
101
|
getOracle(mint) {
|
|
69
102
|
const oracleStr = this.mintOracleMapping.get(mint.toString());
|
|
70
103
|
if (!oracleStr) {
|
|
@@ -72,18 +105,6 @@ class ClendClient {
|
|
|
72
105
|
}
|
|
73
106
|
return new anchor_1.web3.PublicKey(oracleStr);
|
|
74
107
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Get Jupiter quote for a swap
|
|
77
|
-
*/
|
|
78
|
-
async getJupiterQuote(inputMint, outputMint, inputMintDecimals, outputMintDecimals, inputAmountLamports, slippageBps, swapMode) {
|
|
79
|
-
return this.jupiterUtils.getJupiterQuote(inputMint, outputMint, inputMintDecimals, outputMintDecimals, inputAmountLamports, slippageBps, swapMode);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Get Jupiter swap instructions
|
|
83
|
-
*/
|
|
84
|
-
async getJupiterSwap(payer, inputs, quote) {
|
|
85
|
-
return this.jupiterUtils.getJupiterSwap(payer, inputs, quote);
|
|
86
|
-
}
|
|
87
108
|
async send(ixns, additionalSigners = [], additionalLuts = []) {
|
|
88
109
|
const cuPriorityFeeIx = anchor_1.web3.ComputeBudgetProgram.setComputeUnitPrice({
|
|
89
110
|
microLamports: this.cuFeeInMicroLamports,
|
|
@@ -176,11 +197,11 @@ class ClendClient {
|
|
|
176
197
|
return this.send([initIx]);
|
|
177
198
|
}
|
|
178
199
|
// Bank Operations
|
|
179
|
-
async addBank(clendGroup, bankMint,
|
|
200
|
+
async addBank(clendGroup, bankMint, oracleSetupArgs, bankConfig, interestRateConfig) {
|
|
180
201
|
const tokenProgram = (0, utils_1.getTokenProgramForMint)(bankMint);
|
|
181
202
|
const feeStateAccountData = await this.getFeeState();
|
|
182
203
|
const globalFeeWallet = feeStateAccountData.globalFeeWallet;
|
|
183
|
-
const { bank, ixns } = await this.instructions.addBank(clendGroup, this.address(), globalFeeWallet, bankMint, tokenProgram,
|
|
204
|
+
const { bank, ixns } = await this.instructions.addBank(clendGroup, this.address(), globalFeeWallet, bankMint, tokenProgram, oracleSetupArgs, bankConfig, interestRateConfig);
|
|
184
205
|
const txSig = await this.send(ixns);
|
|
185
206
|
return { bank, txSig };
|
|
186
207
|
}
|
|
@@ -511,9 +532,10 @@ class ClendClient {
|
|
|
511
532
|
const ix = await this.instructions.resetBankFees(bankData.group, this.address(), bank);
|
|
512
533
|
return this.send([ix]);
|
|
513
534
|
}
|
|
514
|
-
async liquidateClendAccountWithFlashLoan(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, marginfiLiabFlashLoanBank, liquidatorMarginfiAccount, additionalIxnCount
|
|
535
|
+
async liquidateClendAccountWithFlashLoan(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, marginfiLiabFlashLoanBank, liquidatorMarginfiAccount, additionalIxnCount, // used to calculate the end flash loan index
|
|
536
|
+
swapperOverride) {
|
|
515
537
|
// create instructions
|
|
516
|
-
const result = await this.getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps);
|
|
538
|
+
const result = await this.getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, swapperOverride);
|
|
517
539
|
if (!result) {
|
|
518
540
|
return;
|
|
519
541
|
}
|
|
@@ -546,8 +568,8 @@ class ClendClient {
|
|
|
546
568
|
];
|
|
547
569
|
return this.send(ixns, [], luts);
|
|
548
570
|
}
|
|
549
|
-
async liquidateClendAccount(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps) {
|
|
550
|
-
const result = await this.getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps);
|
|
571
|
+
async liquidateClendAccount(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, swapperOverride) {
|
|
572
|
+
const result = await this.getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, swapperOverride);
|
|
551
573
|
if (!result) {
|
|
552
574
|
return;
|
|
553
575
|
}
|
|
@@ -572,7 +594,12 @@ class ClendClient {
|
|
|
572
594
|
* Must be <= 0.
|
|
573
595
|
* returns: instructions, luts, deposit amount (libaility token)
|
|
574
596
|
*/
|
|
575
|
-
async getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps) {
|
|
597
|
+
async getLiquidateClendAccountIxns(liquidatorClendAccount, liquidateeClendAccount, assetBankData, liabBankData, targetOnChainMaintenanceHealthValue, slippageBps, swapperOverride) {
|
|
598
|
+
let activeSwapper = this.swapper;
|
|
599
|
+
// override swapper if provided
|
|
600
|
+
if (swapperOverride) {
|
|
601
|
+
activeSwapper = swapperOverride;
|
|
602
|
+
}
|
|
576
603
|
utils_1.logger.info("Starting liquidation calculation", {
|
|
577
604
|
liquidatee: liquidateeClendAccount.authority.toString(),
|
|
578
605
|
liquidator: liquidatorClendAccount.authority.toString(),
|
|
@@ -691,30 +718,32 @@ class ClendClient {
|
|
|
691
718
|
// just withdraw the liquidated amount
|
|
692
719
|
// balance for the asset
|
|
693
720
|
const withdrawAssetIx = await this.instructions.withdraw(assetBankData.group, liquidatorClendAccount.key, liquidatorClendAccount.authority, assetBankData.key, liquidatorAssetAta, assetTokenProgram, finalAssetAmount, false, remainingAccounts);
|
|
694
|
-
//
|
|
695
|
-
const swapQuote = await
|
|
696
|
-
|
|
697
|
-
|
|
721
|
+
// get a swap quote
|
|
722
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
723
|
+
payer: liquidatorClendAccount.authority,
|
|
724
|
+
inputMint: assetBankData.mint,
|
|
725
|
+
inputMintDecimals: assetBankData.mintDecimals,
|
|
726
|
+
outputMint: liabBankData.mint,
|
|
727
|
+
outputMintDecimals: liabBankData.mintDecimals,
|
|
728
|
+
inputAmount: finalAssetAmount,
|
|
729
|
+
slippageBps,
|
|
730
|
+
swapMode: "ExactIn",
|
|
731
|
+
});
|
|
732
|
+
const outAmountMin = swapQuote.otherAmountThreshold;
|
|
698
733
|
utils_1.logger.debug("liquidateClendAccount: Jupiter swapQuote for total amount", {
|
|
699
|
-
inAmount: swapQuote.
|
|
700
|
-
outAmount: swapQuote.
|
|
734
|
+
inAmount: swapQuote.inAmount.toString(10),
|
|
735
|
+
outAmount: swapQuote.outAmount.toString(10),
|
|
701
736
|
outAmountMin: outAmountMin.toString(10),
|
|
702
|
-
priceImpactPct: swapQuote.quoteResponse.priceImpactPct,
|
|
703
737
|
});
|
|
704
738
|
// 5. Get Swap Instructions from Jupiter
|
|
705
|
-
const
|
|
706
|
-
inputAmountLamports: new decimal_js_1.default(finalAssetAmount.toString()),
|
|
707
|
-
inputMint: assetBankData.mint,
|
|
708
|
-
outputMint: liabBankData.mint,
|
|
709
|
-
};
|
|
710
|
-
const jupiterSwapIxs = await this.getJupiterSwap(this.address(), swapInputs, swapQuote);
|
|
739
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
711
740
|
const ixns = [
|
|
712
741
|
depositIx, // deposit liability mint into liquidator clend account
|
|
713
742
|
liquidationIx, // liquidate liquidatee clend account
|
|
714
743
|
withdrawAssetIx, // withdraw liquidated asset from liquidator clend account
|
|
715
|
-
...
|
|
744
|
+
...swapIxns.ixns, // swap liquidated asset for liability mint
|
|
716
745
|
];
|
|
717
|
-
return { ixns, luts:
|
|
746
|
+
return { ixns, luts: swapIxns.luts, depositAmount };
|
|
718
747
|
}
|
|
719
748
|
async configureBankInterestRate(bank, interestRateConfig) {
|
|
720
749
|
const bankData = await this.getBank(bank);
|
|
@@ -748,28 +777,28 @@ class ClendClient {
|
|
|
748
777
|
}
|
|
749
778
|
async configureBankOracle(bank, pythOracle, pythOracleFeed) {
|
|
750
779
|
const bankData = await this.getBank(bank);
|
|
751
|
-
const ix = await this.instructions.
|
|
780
|
+
const ix = await this.instructions.configureBankPythOracle(bankData.group, this.address(), bank, pythOracle, pythOracleFeed);
|
|
752
781
|
return this.send([ix]);
|
|
753
782
|
}
|
|
754
783
|
async setBankOperationalState(clendGroup, bank, operationalState) {
|
|
755
784
|
const ix = await this.instructions.setBankOperationalState(clendGroup, this.address(), bank, operationalState);
|
|
756
785
|
return this.send([ix]);
|
|
757
786
|
}
|
|
758
|
-
async depositLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps) {
|
|
787
|
+
async depositLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps, swapperOverride) {
|
|
759
788
|
let ixns = [];
|
|
760
789
|
let luts = [];
|
|
761
790
|
let additionalSigners = [];
|
|
762
791
|
switch (selectedMint.toString()) {
|
|
763
792
|
case collateralMint.toString():
|
|
764
793
|
const collateralParams = await this.getDepositLeverageFromCollateralParams(clendGroup, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps);
|
|
765
|
-
const { ixns: collateralIxns, luts: collateralLuts, additionalSigners: collateralAdditionalSigners, } = await this.getDepositLeverageFromCollateralIxns(clendGroup, this.address(), clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, collateralParams.borrowAmount, depositAmount, slippageBps, 0);
|
|
794
|
+
const { ixns: collateralIxns, luts: collateralLuts, additionalSigners: collateralAdditionalSigners, } = await this.getDepositLeverageFromCollateralIxns(clendGroup, this.address(), clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, collateralParams.borrowAmount, depositAmount, slippageBps, 0, swapperOverride);
|
|
766
795
|
ixns = collateralIxns;
|
|
767
796
|
luts = collateralLuts;
|
|
768
797
|
additionalSigners = collateralAdditionalSigners;
|
|
769
798
|
break;
|
|
770
799
|
case debtMint.toString():
|
|
771
|
-
const debtParams = await this.getDepositLeverageFromDebtParams(clendGroup, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps);
|
|
772
|
-
const { ixns: debtIxns, luts: debtLuts, additionalSigners: debtAdditionalSigners, } = await this.getDepositLeverageFromDebtIxns(clendGroup, this.address(), clendAccount, collateralMint, debtMint, debtParams.debtBankData.mintDecimals, debtParams.collateralBankData.mintDecimals, depositAmount, debtParams.borrowAmount, slippageBps, 0);
|
|
800
|
+
const debtParams = await this.getDepositLeverageFromDebtParams(clendGroup, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps, swapperOverride);
|
|
801
|
+
const { ixns: debtIxns, luts: debtLuts, additionalSigners: debtAdditionalSigners, } = await this.getDepositLeverageFromDebtIxns(clendGroup, this.address(), clendAccount, collateralMint, debtMint, debtParams.debtBankData.mintDecimals, debtParams.collateralBankData.mintDecimals, depositAmount, debtParams.borrowAmount, slippageBps, 0, swapperOverride);
|
|
773
802
|
ixns = debtIxns;
|
|
774
803
|
luts = debtLuts;
|
|
775
804
|
additionalSigners = debtAdditionalSigners;
|
|
@@ -781,7 +810,13 @@ class ClendClient {
|
|
|
781
810
|
}
|
|
782
811
|
async getDepositLeverageFromDebtIxns(clendGroup, user, clendAccount, collateralMint, // e.g., JLP
|
|
783
812
|
debtMint, // e.g., USDC
|
|
784
|
-
debtMintDecimals, collateralMintDecimals, initialUserDebtContributionForSwap, finalLoopBorrowAmount, slippageBps, additionalIxnCount
|
|
813
|
+
debtMintDecimals, collateralMintDecimals, initialUserDebtContributionForSwap, finalLoopBorrowAmount, slippageBps, additionalIxnCount, // For JIT liquidity, etc.
|
|
814
|
+
swapperOverride) {
|
|
815
|
+
// override swapper if provided
|
|
816
|
+
let activeSwapper = this.swapper;
|
|
817
|
+
if (swapperOverride) {
|
|
818
|
+
activeSwapper = swapperOverride;
|
|
819
|
+
}
|
|
785
820
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
786
821
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
787
822
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
@@ -820,31 +855,31 @@ class ClendClient {
|
|
|
820
855
|
// 2. Calculate Total Debt Token for Swap
|
|
821
856
|
const totalDebtTokenForSwap = initialUserDebtContributionForSwap.add(finalLoopBorrowAmount);
|
|
822
857
|
// 3. Get Jupiter Quote for the TOTAL debt token amount
|
|
823
|
-
const swapMode =
|
|
824
|
-
const swapQuote = await
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
858
|
+
const swapMode = "ExactIn";
|
|
859
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
860
|
+
payer: user,
|
|
861
|
+
inputMint: debtMint,
|
|
862
|
+
inputMintDecimals: debtMintDecimals,
|
|
863
|
+
outputMint: collateralMint,
|
|
864
|
+
outputMintDecimals: collateralMintDecimals,
|
|
865
|
+
inputAmount: totalDebtTokenForSwap,
|
|
866
|
+
slippageBps,
|
|
867
|
+
swapMode,
|
|
868
|
+
});
|
|
828
869
|
utils_1.logger.debug("getDepositLeverageFromDebtIxns: Jupiter swapQuote for total amount", {
|
|
829
|
-
inAmount: swapQuote.
|
|
830
|
-
outAmount: swapQuote.
|
|
831
|
-
otherAmountThreshold: swapQuote.
|
|
832
|
-
priceImpactPct: swapQuote.quoteResponse.priceImpactPct,
|
|
870
|
+
inAmount: swapQuote.inAmount, // Should match totalDebtTokenForSwap
|
|
871
|
+
outAmount: swapQuote.outAmount, // This is the gross JLP output
|
|
872
|
+
otherAmountThreshold: swapQuote.otherAmountThreshold, // Min JLP
|
|
833
873
|
});
|
|
834
874
|
// Ensure the expectedCollateralOutAmount (passed in) is consistent with the quote's minimum
|
|
835
875
|
// This serves as a sanity check; the instruction should use the quote's threshold.
|
|
836
876
|
// deposit up to amount == true as well
|
|
837
|
-
const optimisticCollateralFromQuote = new anchor_1.BN(swapQuote.
|
|
877
|
+
const optimisticCollateralFromQuote = new anchor_1.BN(swapQuote.outAmount);
|
|
838
878
|
// 4. Get User ATAs
|
|
839
879
|
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, user, true, debtTokenProgram);
|
|
840
880
|
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, user, true, collateralTokenProgram);
|
|
841
881
|
// 5. Get Swap Instructions from Jupiter
|
|
842
|
-
const
|
|
843
|
-
inputAmountLamports: new decimal_js_1.default(totalDebtTokenForSwap.toString()),
|
|
844
|
-
inputMint: debtMint,
|
|
845
|
-
outputMint: collateralMint,
|
|
846
|
-
};
|
|
847
|
-
const jupiterSwapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
882
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
848
883
|
// 6. Create Clend Protocol Instructions
|
|
849
884
|
const borrowIx = await this.instructions.borrow(clendGroup, clendAccount, // clendAccount is guaranteed to be non-null here
|
|
850
885
|
user, debtBank, userDebtAta, // Borrow into user's ATA
|
|
@@ -858,7 +893,7 @@ class ClendClient {
|
|
|
858
893
|
// Order: Borrow additional debt, then swap combined debt, then deposit resulting collateral
|
|
859
894
|
const ixnsWithoutFlashLoan = [
|
|
860
895
|
borrowIx,
|
|
861
|
-
...
|
|
896
|
+
...swapIxns.ixns,
|
|
862
897
|
depositIx,
|
|
863
898
|
];
|
|
864
899
|
// 8. Wrap in Flash Loan
|
|
@@ -886,23 +921,38 @@ class ClendClient {
|
|
|
886
921
|
return {
|
|
887
922
|
clendAccount,
|
|
888
923
|
ixns,
|
|
889
|
-
luts:
|
|
924
|
+
luts: swapIxns.luts,
|
|
890
925
|
additionalSigners,
|
|
891
926
|
};
|
|
892
927
|
}
|
|
893
|
-
async getDepositLeverageFromCollateralIxns(clendGroup, user, clendAccount, collateralMint, debtMint, debtMintDecimals, collateralMintDecimals, borrowAmount, depositAmount, slippageBps, additionalIxnCount
|
|
928
|
+
async getDepositLeverageFromCollateralIxns(clendGroup, user, clendAccount, collateralMint, debtMint, debtMintDecimals, collateralMintDecimals, borrowAmount, depositAmount, slippageBps, additionalIxnCount, // used to correctly offset the flash loan index
|
|
929
|
+
swapperOverride) {
|
|
930
|
+
// override swapper if provided
|
|
931
|
+
let activeSwapper = this.swapper;
|
|
932
|
+
if (swapperOverride) {
|
|
933
|
+
activeSwapper = swapperOverride;
|
|
934
|
+
}
|
|
894
935
|
// Get token programs
|
|
895
936
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
896
937
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
897
938
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
898
939
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
899
940
|
// Get Jupiter quote for swapping debt token to collateral token
|
|
900
|
-
const swapMode =
|
|
901
|
-
const swapQuote = await
|
|
941
|
+
const swapMode = "ExactIn";
|
|
942
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
943
|
+
payer: user,
|
|
944
|
+
inputMint: debtMint,
|
|
945
|
+
inputMintDecimals: debtMintDecimals,
|
|
946
|
+
outputMint: collateralMint,
|
|
947
|
+
outputMintDecimals: collateralMintDecimals,
|
|
948
|
+
inputAmount: borrowAmount,
|
|
949
|
+
slippageBps,
|
|
950
|
+
swapMode,
|
|
951
|
+
});
|
|
902
952
|
utils_1.logger.debug("depositLeverage swapQuote", {
|
|
903
|
-
inAmount: swapQuote.
|
|
904
|
-
outAmount: swapQuote.
|
|
905
|
-
|
|
953
|
+
inAmount: swapQuote.inAmount.toString(10),
|
|
954
|
+
outAmount: swapQuote.outAmount.toString(10),
|
|
955
|
+
otherAmountThreshold: swapQuote.otherAmountThreshold.toString(10),
|
|
906
956
|
});
|
|
907
957
|
let activeBanks = [];
|
|
908
958
|
const additionalSigners = [];
|
|
@@ -941,14 +991,9 @@ class ClendClient {
|
|
|
941
991
|
}
|
|
942
992
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
943
993
|
// Get swap instructions
|
|
944
|
-
const
|
|
945
|
-
inputAmountLamports: new decimal_js_1.default(borrowAmount.toString()),
|
|
946
|
-
inputMint: debtMint,
|
|
947
|
-
outputMint: collateralMint,
|
|
948
|
-
};
|
|
949
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
994
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
950
995
|
// Calculate additional collateral from swap
|
|
951
|
-
const additionalCollateralAmount =
|
|
996
|
+
const additionalCollateralAmount = swapQuote.outAmount;
|
|
952
997
|
const totalCollateralAmount = depositAmount.add(additionalCollateralAmount);
|
|
953
998
|
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, user, true, debtTokenProgram);
|
|
954
999
|
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, user, true, collateralTokenProgram);
|
|
@@ -960,7 +1005,7 @@ class ClendClient {
|
|
|
960
1005
|
// add lending and swap instructions
|
|
961
1006
|
const ixnsWithoutFlashLoan = [
|
|
962
1007
|
borrowIx,
|
|
963
|
-
...
|
|
1008
|
+
...swapIxns.ixns,
|
|
964
1009
|
depositIx,
|
|
965
1010
|
];
|
|
966
1011
|
// If the clend account is being created, we need to add 1 to the endIndex
|
|
@@ -987,7 +1032,7 @@ class ClendClient {
|
|
|
987
1032
|
return {
|
|
988
1033
|
clendAccount,
|
|
989
1034
|
ixns,
|
|
990
|
-
luts:
|
|
1035
|
+
luts: swapIxns.luts,
|
|
991
1036
|
additionalSigners,
|
|
992
1037
|
};
|
|
993
1038
|
}
|
|
@@ -1062,7 +1107,12 @@ class ClendClient {
|
|
|
1062
1107
|
async getDepositLeverageFromDebtParams(clendGroup, collateralMint, // The asset being leveraged (e.g., JLP)
|
|
1063
1108
|
debtMint, // The asset provided initially by the user (e.g., USDC)
|
|
1064
1109
|
initialUserDebtContributionForSwap, // User's initial DEBT token for the swap
|
|
1065
|
-
targetLeverage, slippageBps) {
|
|
1110
|
+
targetLeverage, slippageBps, swapperOverride) {
|
|
1111
|
+
// override swapper if provided
|
|
1112
|
+
let activeSwapper = this.swapper;
|
|
1113
|
+
if (swapperOverride) {
|
|
1114
|
+
activeSwapper = swapperOverride;
|
|
1115
|
+
}
|
|
1066
1116
|
// 1. Get decimals and bank data
|
|
1067
1117
|
const collateralDecimals = (0, utils_1.getTokenDecimalsForMint)(collateralMint);
|
|
1068
1118
|
const debtDecimals = (0, utils_1.getTokenDecimalsForMint)(debtMint);
|
|
@@ -1093,12 +1143,18 @@ class ClendClient {
|
|
|
1093
1143
|
// This is the user's initial contribution + what's borrowed from the protocol
|
|
1094
1144
|
const totalDebtTokenForSwap = initialUserDebtContributionForSwap.add(finalLoopBorrowAmount);
|
|
1095
1145
|
// 7. Calculate Expected COLLATERAL Output from swapping the total DEBT token amount
|
|
1096
|
-
const swapQuote = await
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1146
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1147
|
+
payer: anchor_1.web3.PublicKey.default, // doesnt matter right now
|
|
1148
|
+
inputMint: debtMint,
|
|
1149
|
+
inputMintDecimals: debtDecimals,
|
|
1150
|
+
outputMint: collateralMint,
|
|
1151
|
+
outputMintDecimals: collateralDecimals,
|
|
1152
|
+
inputAmount: totalDebtTokenForSwap,
|
|
1153
|
+
slippageBps,
|
|
1154
|
+
swapMode: "ExactIn",
|
|
1155
|
+
});
|
|
1100
1156
|
// Use the minimum amount threshold from the quote for safety in the final deposit instruction
|
|
1101
|
-
const expectedCollateralOutAmount = new anchor_1.BN(swapQuote.
|
|
1157
|
+
const expectedCollateralOutAmount = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1102
1158
|
// --- Logging ---
|
|
1103
1159
|
const finalLoopBorrowAmountUi = (0, clend_common_1.amountToUi)(finalLoopBorrowAmount, debtDecimals);
|
|
1104
1160
|
const totalDebtTokenForSwapUi = (0, clend_common_1.amountToUi)(totalDebtTokenForSwap, debtDecimals);
|
|
@@ -1127,19 +1183,19 @@ class ClendClient {
|
|
|
1127
1183
|
collateralBankData,
|
|
1128
1184
|
};
|
|
1129
1185
|
}
|
|
1130
|
-
async withdrawLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps) {
|
|
1186
|
+
async withdrawLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps, swapperOverride) {
|
|
1131
1187
|
let ixns = [];
|
|
1132
1188
|
let luts = [];
|
|
1133
1189
|
switch (selectedMint.toString()) {
|
|
1134
1190
|
case collateralMint.toString():
|
|
1135
|
-
const collateralParams = await this.getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps);
|
|
1136
|
-
const { ixns: collateralIxns, luts: collateralLuts } = await this.getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, withdrawAll, collateralParams.debtToRepay, collateralParams.collateralToWithdraw, slippageBps, 0);
|
|
1191
|
+
const collateralParams = await this.getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps, swapperOverride);
|
|
1192
|
+
const { ixns: collateralIxns, luts: collateralLuts } = await this.getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralParams.collateralBankData.mintDecimals, collateralParams.debtBankData.mintDecimals, withdrawAll, collateralParams.debtToRepay, collateralParams.collateralToWithdraw, slippageBps, 0, swapperOverride);
|
|
1137
1193
|
ixns = collateralIxns;
|
|
1138
1194
|
luts = collateralLuts;
|
|
1139
1195
|
break;
|
|
1140
1196
|
case debtMint.toString():
|
|
1141
|
-
const debtParams = await this.getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps);
|
|
1142
|
-
const { ixns: debtIxns, luts: debtLuts } = await this.getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, debtParams.collateralBankData.mintDecimals, debtParams.debtBankData.mintDecimals, withdrawAll, debtParams.debtToRepay, debtParams.collateralToWithdraw, withdrawAmount, slippageBps, 0);
|
|
1197
|
+
const debtParams = await this.getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps, swapperOverride);
|
|
1198
|
+
const { ixns: debtIxns, luts: debtLuts } = await this.getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, debtParams.collateralBankData.mintDecimals, debtParams.debtBankData.mintDecimals, withdrawAll, debtParams.debtToRepay, debtParams.collateralToWithdraw, withdrawAmount, slippageBps, 0, swapperOverride);
|
|
1143
1199
|
ixns = debtIxns;
|
|
1144
1200
|
luts = debtLuts;
|
|
1145
1201
|
break;
|
|
@@ -1149,7 +1205,12 @@ class ClendClient {
|
|
|
1149
1205
|
// Send transaction
|
|
1150
1206
|
return this.send(ixns, [], luts);
|
|
1151
1207
|
}
|
|
1152
|
-
async getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, slippageBps, additionalIxnCount) {
|
|
1208
|
+
async getWithdrawLeverageCollateralIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, slippageBps, additionalIxnCount, swapperOverride) {
|
|
1209
|
+
// override swapper if provided
|
|
1210
|
+
let activeSwapper = this.swapper;
|
|
1211
|
+
if (swapperOverride) {
|
|
1212
|
+
activeSwapper = swapperOverride;
|
|
1213
|
+
}
|
|
1153
1214
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1154
1215
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1155
1216
|
// Get remaining accounts for flash loan
|
|
@@ -1165,10 +1226,19 @@ class ClendClient {
|
|
|
1165
1226
|
}
|
|
1166
1227
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
1167
1228
|
// Get Jupiter quote for swapping collateral to debt token (ExactOut mode)
|
|
1168
|
-
const swapMode =
|
|
1169
|
-
const swapQuote = await
|
|
1229
|
+
const swapMode = "ExactOut";
|
|
1230
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1231
|
+
payer: clendAccountData.authority,
|
|
1232
|
+
inputMint: collateralMint,
|
|
1233
|
+
inputMintDecimals: collateralDecimals,
|
|
1234
|
+
outputMint: debtMint,
|
|
1235
|
+
outputMintDecimals: debtDecimals,
|
|
1236
|
+
inputAmount: debtToRepay,
|
|
1237
|
+
slippageBps,
|
|
1238
|
+
swapMode,
|
|
1239
|
+
});
|
|
1170
1240
|
// set collateralToSwap to the inAmount from the swap quote
|
|
1171
|
-
const collateralToSwap = swapQuote.
|
|
1241
|
+
const collateralToSwap = swapQuote.inAmount;
|
|
1172
1242
|
utils_1.logger.debug("withdrawLeverage collateralToSwap", {
|
|
1173
1243
|
collateralToSwap,
|
|
1174
1244
|
});
|
|
@@ -1181,7 +1251,7 @@ class ClendClient {
|
|
|
1181
1251
|
utils_1.logger.debug("withdrawLeverage swapInputs", {
|
|
1182
1252
|
swapInputs,
|
|
1183
1253
|
});
|
|
1184
|
-
const
|
|
1254
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1185
1255
|
utils_1.logger.info(`swapIxns fetched`);
|
|
1186
1256
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
1187
1257
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
@@ -1197,7 +1267,7 @@ class ClendClient {
|
|
|
1197
1267
|
// Assemble all instructions without flash loan
|
|
1198
1268
|
const ixnsWithoutFlashLoan = [
|
|
1199
1269
|
withdrawIx,
|
|
1200
|
-
...
|
|
1270
|
+
...swapIxns.ixns,
|
|
1201
1271
|
repayIx,
|
|
1202
1272
|
];
|
|
1203
1273
|
utils_1.logger.info(`ixnsWithoutFlashLoan set`);
|
|
@@ -1211,9 +1281,14 @@ class ClendClient {
|
|
|
1211
1281
|
...ixnsWithoutFlashLoan,
|
|
1212
1282
|
endFlashLoanIx,
|
|
1213
1283
|
];
|
|
1214
|
-
return { ixns: instructions, luts:
|
|
1284
|
+
return { ixns: instructions, luts: swapIxns.luts };
|
|
1215
1285
|
}
|
|
1216
|
-
async getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, desiredNetDebtToReceive, slippageBps, additionalIxnCount) {
|
|
1286
|
+
async getWithdrawLeverageDebtIxns(clendGroup, clendAccount, collateralMint, debtMint, collateralDecimals, debtDecimals, withdrawAll, debtToRepay, collateralToWithdraw, desiredNetDebtToReceive, slippageBps, additionalIxnCount, swapperOverride) {
|
|
1287
|
+
// override swapper if provided
|
|
1288
|
+
let activeSwapper = this.swapper;
|
|
1289
|
+
if (swapperOverride) {
|
|
1290
|
+
activeSwapper = swapperOverride;
|
|
1291
|
+
}
|
|
1217
1292
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1218
1293
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1219
1294
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
@@ -1231,24 +1306,26 @@ class ClendClient {
|
|
|
1231
1306
|
// 1. Determine Total USDC Needed from the Swap
|
|
1232
1307
|
// This is the amount needed to repay Clend's debt AND give the user their desired net withdrawal.
|
|
1233
1308
|
const totalDebtToReceive = debtToRepay.add(desiredNetDebtToReceive);
|
|
1234
|
-
const swapMode =
|
|
1235
|
-
const swapQuote = await
|
|
1236
|
-
|
|
1237
|
-
|
|
1309
|
+
const swapMode = "ExactIn";
|
|
1310
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1311
|
+
payer: clendAccountData.authority,
|
|
1312
|
+
inputMint: collateralMint,
|
|
1313
|
+
inputMintDecimals: collateralDecimals,
|
|
1314
|
+
outputMint: debtMint,
|
|
1315
|
+
outputMintDecimals: debtDecimals,
|
|
1316
|
+
inputAmount: collateralToWithdraw,
|
|
1317
|
+
slippageBps,
|
|
1318
|
+
swapMode,
|
|
1319
|
+
});
|
|
1320
|
+
const minUsdcReceivedFromSwap_BN = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1238
1321
|
utils_1.logger.debug("getWithdrawLeverageDebtIxns: collateral and debt details", {
|
|
1239
1322
|
debtToRepay: debtToRepay.toString(),
|
|
1240
1323
|
desiredNetDebtToReceive: desiredNetDebtToReceive.toString(),
|
|
1241
1324
|
totalDebtToReceive: totalDebtToReceive.toString(),
|
|
1242
1325
|
minUsdcReceivedFromSwap_BN: minUsdcReceivedFromSwap_BN.toString(),
|
|
1243
1326
|
});
|
|
1244
|
-
// 3. Get Swap Instructions from
|
|
1245
|
-
|
|
1246
|
-
const swapInputs = {
|
|
1247
|
-
inputAmountLamports: new decimal_js_1.default(collateralToWithdraw.toString()),
|
|
1248
|
-
inputMint: collateralMint,
|
|
1249
|
-
outputMint: debtMint,
|
|
1250
|
-
};
|
|
1251
|
-
const jupiterSwapIxs = await this.getJupiterSwap(clendAccountData.authority, swapInputs, swapQuote);
|
|
1327
|
+
// 3. Get Swap Instructions from swapper
|
|
1328
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1252
1329
|
utils_1.logger.info(`swapIxns fetched for ReceiveDebtToken`);
|
|
1253
1330
|
// --- ATAs and Clend Instructions (largely similar structure) ---
|
|
1254
1331
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
@@ -1266,9 +1343,9 @@ class ClendClient {
|
|
|
1266
1343
|
// Assemble instructions
|
|
1267
1344
|
const ixnsWithoutFlashLoan = [
|
|
1268
1345
|
withdrawIx,
|
|
1269
|
-
...
|
|
1346
|
+
...swapIxns.ixns, // Swap all withdrawn collateral to debt
|
|
1270
1347
|
repayIx, // Repay the debt portion
|
|
1271
|
-
]; // User is left with the remaining
|
|
1348
|
+
]; // User is left with the remaining debt in their ATA
|
|
1272
1349
|
// Flash Loan Wrapping (same as before)
|
|
1273
1350
|
const cuIxns = 2;
|
|
1274
1351
|
const endIndex = new anchor_1.BN(cuIxns + ixnsWithoutFlashLoan.length + 1 + additionalIxnCount);
|
|
@@ -1278,11 +1355,16 @@ class ClendClient {
|
|
|
1278
1355
|
...ixnsWithoutFlashLoan,
|
|
1279
1356
|
endFlashLoanIx,
|
|
1280
1357
|
];
|
|
1281
|
-
return { ixns: instructions, luts:
|
|
1358
|
+
return { ixns: instructions, luts: swapIxns.luts };
|
|
1282
1359
|
}
|
|
1283
1360
|
// caller will receive desiredNetWithdraw, the position will be adjusted accordingly
|
|
1284
1361
|
// receive the collateral mint
|
|
1285
|
-
async getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, slippageBps) {
|
|
1362
|
+
async getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, slippageBps, swapperOverride) {
|
|
1363
|
+
// override swapper if provided
|
|
1364
|
+
let activeSwapper = this.swapper;
|
|
1365
|
+
if (swapperOverride) {
|
|
1366
|
+
activeSwapper = swapperOverride;
|
|
1367
|
+
}
|
|
1286
1368
|
utils_1.logger.info("getNetWithdrawParams", {
|
|
1287
1369
|
desiredNetWithdraw: desiredNetWithdraw.toString(),
|
|
1288
1370
|
withdrawAll,
|
|
@@ -1370,11 +1452,17 @@ class ClendClient {
|
|
|
1370
1452
|
// --- Step 6: Get a Jupiter Quote for the Swap ---
|
|
1371
1453
|
// Query Jupiter for an EXACT_OUT swap to find out exactly how much collateral
|
|
1372
1454
|
// is needed to get the final amount of debt we need to repay.
|
|
1373
|
-
const swapQuote = await
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1455
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1456
|
+
payer: clendAccountData.authority,
|
|
1457
|
+
inputMint: collateralMint,
|
|
1458
|
+
inputMintDecimals: collateralDecimals,
|
|
1459
|
+
outputMint: debtMint,
|
|
1460
|
+
outputMintDecimals: debtDecimals,
|
|
1461
|
+
inputAmount: debtToRepay,
|
|
1462
|
+
slippageBps,
|
|
1463
|
+
swapMode: "ExactOut",
|
|
1464
|
+
});
|
|
1465
|
+
const collateralNeededForSwap = new anchor_1.BN(swapQuote.inAmount);
|
|
1378
1466
|
// --- Step 7: Calculate the Final Total Collateral to Withdraw ---
|
|
1379
1467
|
// This is the sum of what the user gets (desiredNetWithdraw) and what the swap needs.
|
|
1380
1468
|
collateralToWithdraw = desiredNetWithdraw.add(collateralNeededForSwap);
|
|
@@ -1396,7 +1484,12 @@ class ClendClient {
|
|
|
1396
1484
|
}
|
|
1397
1485
|
// caller will receive desiredNetWithdraw, the position will be adjusted accordingly
|
|
1398
1486
|
// receive the debt mint
|
|
1399
|
-
async getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, slippageBps) {
|
|
1487
|
+
async getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, desiredNetWithdraw, withdrawAll, slippageBps, swapperOverride) {
|
|
1488
|
+
// override swapper if provided
|
|
1489
|
+
let activeSwapper = this.swapper;
|
|
1490
|
+
if (swapperOverride) {
|
|
1491
|
+
activeSwapper = swapperOverride;
|
|
1492
|
+
}
|
|
1400
1493
|
utils_1.logger.info("getNetWithdrawDebtParams", {
|
|
1401
1494
|
desiredNetWithdraw: desiredNetWithdraw.toString(),
|
|
1402
1495
|
withdrawAll,
|
|
@@ -1476,9 +1569,18 @@ class ClendClient {
|
|
|
1476
1569
|
// The total value we need to get from selling JLP is the debt we must repay
|
|
1477
1570
|
const totalDebtNeededFromSwap = debtToRepay.add(desiredNetWithdraw);
|
|
1478
1571
|
// Now, find how much collateral is needed to produce this swap via swap
|
|
1479
|
-
const swapQuote = await
|
|
1480
|
-
|
|
1481
|
-
|
|
1572
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1573
|
+
payer: clendAccountData.authority,
|
|
1574
|
+
inputMint: collateralMint,
|
|
1575
|
+
inputMintDecimals: collateralDecimals,
|
|
1576
|
+
outputMint: debtMint,
|
|
1577
|
+
outputMintDecimals: debtDecimals,
|
|
1578
|
+
inputAmount: totalDebtNeededFromSwap,
|
|
1579
|
+
slippageBps,
|
|
1580
|
+
swapMode: "ExactOut",
|
|
1581
|
+
});
|
|
1582
|
+
// The answer from swapper is the total collateral we must withdraw.
|
|
1583
|
+
collateralToWithdraw = swapQuote.inAmount;
|
|
1482
1584
|
// --- Step 4: Final Sanity Check ---
|
|
1483
1585
|
if (collateralToWithdraw.gt(collateralAmount)) {
|
|
1484
1586
|
throw new Error("Total required collateral for withdrawal and swap exceeds the available balance.");
|
|
@@ -1495,9 +1597,9 @@ class ClendClient {
|
|
|
1495
1597
|
debtBankData,
|
|
1496
1598
|
};
|
|
1497
1599
|
}
|
|
1498
|
-
async adjustLeverage(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps) {
|
|
1600
|
+
async adjustLeverage(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps, swapperOverride) {
|
|
1499
1601
|
const params = await this.getAdjustLeverageParams(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps);
|
|
1500
|
-
const { ixns, luts } = await this.getAdjustLeverageIxns(clendGroup, clendAccount, this.address(), params.debtBankData, params.collateralBankData, params.isIncrease, params.finalDebtDeltaUi, params.finalCollateralDeltaUi, slippageBps, 0);
|
|
1602
|
+
const { ixns, luts } = await this.getAdjustLeverageIxns(clendGroup, clendAccount, this.address(), params.debtBankData, params.collateralBankData, params.isIncrease, params.finalDebtDeltaUi, params.finalCollateralDeltaUi, slippageBps, 0, swapperOverride);
|
|
1501
1603
|
// Send transaction
|
|
1502
1604
|
return this.send(ixns, [], luts);
|
|
1503
1605
|
}
|
|
@@ -1705,7 +1807,12 @@ class ClendClient {
|
|
|
1705
1807
|
*/
|
|
1706
1808
|
async getAdjustLeverageIxns(clendGroup, clendAccount, user, debtBankData, collateralBankData, isIncrease, finalDebtDeltaUi, // Use the final adjusted value from getAdjustLeverageParams
|
|
1707
1809
|
finalCollateralDeltaUi, // Use the final adjusted value from getAdjustLeverageParams
|
|
1708
|
-
slippageBps, additionalIxnCount) {
|
|
1810
|
+
slippageBps, additionalIxnCount, swapperOverride) {
|
|
1811
|
+
// override swapper if provided
|
|
1812
|
+
let activeSwapper = this.swapper;
|
|
1813
|
+
if (swapperOverride) {
|
|
1814
|
+
activeSwapper = swapperOverride;
|
|
1815
|
+
}
|
|
1709
1816
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
1710
1817
|
if (!clendAccountData) {
|
|
1711
1818
|
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
@@ -1740,34 +1847,37 @@ class ClendClient {
|
|
|
1740
1847
|
additionalDebtAmount: additionalDebtAmount.toString(),
|
|
1741
1848
|
});
|
|
1742
1849
|
// Get Jupiter quote for swapping debt token to collateral token (ExactIn)
|
|
1743
|
-
const swapMode =
|
|
1744
|
-
const swapQuote = await
|
|
1745
|
-
|
|
1850
|
+
const swapMode = "ExactIn";
|
|
1851
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1852
|
+
payer: user,
|
|
1853
|
+
inputMint: debtBankData.mint,
|
|
1854
|
+
inputMintDecimals: debtBankData.mintDecimals,
|
|
1855
|
+
outputMint: collateralBankData.mint,
|
|
1856
|
+
outputMintDecimals: collateralBankData.mintDecimals,
|
|
1857
|
+
inputAmount: additionalDebtAmount,
|
|
1858
|
+
slippageBps,
|
|
1859
|
+
swapMode,
|
|
1860
|
+
});
|
|
1746
1861
|
utils_1.logger.debug("swapQuote calculated (Increase)", {
|
|
1747
|
-
inAmount: swapQuote.
|
|
1748
|
-
outAmount: swapQuote.
|
|
1749
|
-
|
|
1862
|
+
inAmount: swapQuote.inAmount.toString(),
|
|
1863
|
+
outAmount: swapQuote.outAmount.toString(),
|
|
1864
|
+
otherAmountThreshold: swapQuote.otherAmountThreshold.toString(),
|
|
1750
1865
|
});
|
|
1751
1866
|
// Get swap instructions
|
|
1752
|
-
const
|
|
1753
|
-
inputAmountLamports: new decimal_js_1.default(additionalDebtAmount.toString()),
|
|
1754
|
-
inputMint: debtBankData.mint,
|
|
1755
|
-
outputMint: collateralBankData.mint,
|
|
1756
|
-
};
|
|
1757
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
1867
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1758
1868
|
// Borrow the final adjusted debt amount
|
|
1759
1869
|
const borrowIx = await this.instructions.borrow(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, additionalDebtAmount, // Use final adjusted amount
|
|
1760
1870
|
remainingAccounts);
|
|
1761
1871
|
// Calculate additional collateral expected from swap (based on quote)
|
|
1762
|
-
const additionalCollateralAmount =
|
|
1872
|
+
const additionalCollateralAmount = swapQuote.outAmount;
|
|
1763
1873
|
utils_1.logger.debug("additionalCollateralAmount expected from swap", {
|
|
1764
1874
|
additionalCollateralAmount: additionalCollateralAmount.toString(),
|
|
1765
1875
|
});
|
|
1766
1876
|
// Deposit additional collateral received from swap
|
|
1767
1877
|
const depositIx = await this.instructions.deposit(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, additionalCollateralAmount, // Deposit what the swap provides
|
|
1768
1878
|
true, remainingAccounts);
|
|
1769
|
-
instructions.push(borrowIx, ...
|
|
1770
|
-
swapLookupTables =
|
|
1879
|
+
instructions.push(borrowIx, ...swapIxns.ixns, depositIx);
|
|
1880
|
+
swapLookupTables = swapIxns.luts;
|
|
1771
1881
|
}
|
|
1772
1882
|
else {
|
|
1773
1883
|
// Decreasing Leverage
|
|
@@ -1782,22 +1892,24 @@ class ClendClient {
|
|
|
1782
1892
|
});
|
|
1783
1893
|
// Get Jupiter quote for swapping collateral token to debt token (ExactOut)
|
|
1784
1894
|
// Target the final buffered debt repayment amount
|
|
1785
|
-
const swapMode =
|
|
1786
|
-
const swapQuote = await
|
|
1787
|
-
|
|
1788
|
-
|
|
1895
|
+
const swapMode = "ExactOut";
|
|
1896
|
+
const swapQuote = await activeSwapper.getQuote({
|
|
1897
|
+
payer: clendAccountData.authority,
|
|
1898
|
+
inputMint: collateralBankData.mint,
|
|
1899
|
+
inputMintDecimals: collateralBankData.mintDecimals,
|
|
1900
|
+
outputMint: debtBankData.mint,
|
|
1901
|
+
outputMintDecimals: debtBankData.mintDecimals,
|
|
1902
|
+
inputAmount: finalDebtToRepayBN,
|
|
1903
|
+
slippageBps,
|
|
1904
|
+
swapMode,
|
|
1905
|
+
});
|
|
1906
|
+
const estimatedCollateralInput = swapQuote.inAmount;
|
|
1789
1907
|
utils_1.logger.debug("swapQuote calculated (Decrease)", {
|
|
1790
1908
|
targetOutput: finalDebtToRepayBN.toString(),
|
|
1791
1909
|
estimatedInput: estimatedCollateralInput,
|
|
1792
1910
|
maxInputCalculated: finalCollateralToWithdrawBN.toString(), // Compare Jupiter estimate vs our max calc
|
|
1793
|
-
priceImpactPct: swapQuote.quoteResponse.priceImpactPct,
|
|
1794
1911
|
});
|
|
1795
|
-
const
|
|
1796
|
-
inputAmountLamports: new decimal_js_1.default(swapQuote.quoteResponse.inAmount.toString()),
|
|
1797
|
-
inputMint: collateralBankData.mint,
|
|
1798
|
-
outputMint: debtBankData.mint,
|
|
1799
|
-
};
|
|
1800
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
1912
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1801
1913
|
// Withdraw the CALCULATED MAXIMUM collateral needed (includes swap input + buffer)
|
|
1802
1914
|
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, finalCollateralToWithdrawBN, // Use the final adjusted amount from params
|
|
1803
1915
|
false, // Not withdrawing all
|
|
@@ -1806,8 +1918,8 @@ class ClendClient {
|
|
|
1806
1918
|
const repayIx = await this.instructions.repay(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, finalDebtToRepayBN, // Use the final adjusted amount from params
|
|
1807
1919
|
false, // Not repaying all
|
|
1808
1920
|
remainingAccounts);
|
|
1809
|
-
instructions.push(withdrawIx, ...
|
|
1810
|
-
swapLookupTables =
|
|
1921
|
+
instructions.push(withdrawIx, ...swapIxns.ixns, repayIx);
|
|
1922
|
+
swapLookupTables = swapIxns.luts;
|
|
1811
1923
|
}
|
|
1812
1924
|
// --- Flash Loan Wrapping ---
|
|
1813
1925
|
const cuIxns = 2; // Assuming 2 compute budget instructions are added later
|