@carrot-protocol/clend-rpc 0.1.26-p-withdraw-dev-e12dfc4 → 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 +27 -34
- package/dist/rpc.js +282 -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
|
|
@@ -883,21 +918,41 @@ class ClendClient {
|
|
|
883
918
|
...ixnsWithoutFlashLoan,
|
|
884
919
|
endFlashLoanIx,
|
|
885
920
|
];
|
|
886
|
-
return {
|
|
921
|
+
return {
|
|
922
|
+
clendAccount,
|
|
923
|
+
ixns,
|
|
924
|
+
luts: swapIxns.luts,
|
|
925
|
+
additionalSigners,
|
|
926
|
+
};
|
|
887
927
|
}
|
|
888
|
-
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
|
+
}
|
|
889
935
|
// Get token programs
|
|
890
936
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
891
937
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
892
938
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
893
939
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
894
940
|
// Get Jupiter quote for swapping debt token to collateral token
|
|
895
|
-
const swapMode =
|
|
896
|
-
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
|
+
});
|
|
897
952
|
utils_1.logger.debug("depositLeverage swapQuote", {
|
|
898
|
-
inAmount: swapQuote.
|
|
899
|
-
outAmount: swapQuote.
|
|
900
|
-
|
|
953
|
+
inAmount: swapQuote.inAmount.toString(10),
|
|
954
|
+
outAmount: swapQuote.outAmount.toString(10),
|
|
955
|
+
otherAmountThreshold: swapQuote.otherAmountThreshold.toString(10),
|
|
901
956
|
});
|
|
902
957
|
let activeBanks = [];
|
|
903
958
|
const additionalSigners = [];
|
|
@@ -936,14 +991,9 @@ class ClendClient {
|
|
|
936
991
|
}
|
|
937
992
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
938
993
|
// Get swap instructions
|
|
939
|
-
const
|
|
940
|
-
inputAmountLamports: new decimal_js_1.default(borrowAmount.toString()),
|
|
941
|
-
inputMint: debtMint,
|
|
942
|
-
outputMint: collateralMint,
|
|
943
|
-
};
|
|
944
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
994
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
945
995
|
// Calculate additional collateral from swap
|
|
946
|
-
const additionalCollateralAmount =
|
|
996
|
+
const additionalCollateralAmount = swapQuote.outAmount;
|
|
947
997
|
const totalCollateralAmount = depositAmount.add(additionalCollateralAmount);
|
|
948
998
|
const userDebtAta = (0, spl_token_1.getAssociatedTokenAddressSync)(debtMint, user, true, debtTokenProgram);
|
|
949
999
|
const userCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(collateralMint, user, true, collateralTokenProgram);
|
|
@@ -955,7 +1005,7 @@ class ClendClient {
|
|
|
955
1005
|
// add lending and swap instructions
|
|
956
1006
|
const ixnsWithoutFlashLoan = [
|
|
957
1007
|
borrowIx,
|
|
958
|
-
...
|
|
1008
|
+
...swapIxns.ixns,
|
|
959
1009
|
depositIx,
|
|
960
1010
|
];
|
|
961
1011
|
// If the clend account is being created, we need to add 1 to the endIndex
|
|
@@ -979,7 +1029,12 @@ class ClendClient {
|
|
|
979
1029
|
...ixnsWithoutFlashLoan,
|
|
980
1030
|
endFlashLoanIx,
|
|
981
1031
|
];
|
|
982
|
-
return {
|
|
1032
|
+
return {
|
|
1033
|
+
clendAccount,
|
|
1034
|
+
ixns,
|
|
1035
|
+
luts: swapIxns.luts,
|
|
1036
|
+
additionalSigners,
|
|
1037
|
+
};
|
|
983
1038
|
}
|
|
984
1039
|
async getDepositLeverageFromCollateralParams(clendGroup, collateralMint, debtMint, depositAmount, targetLeverage, slippageBps) {
|
|
985
1040
|
// Get decimals
|
|
@@ -1052,7 +1107,12 @@ class ClendClient {
|
|
|
1052
1107
|
async getDepositLeverageFromDebtParams(clendGroup, collateralMint, // The asset being leveraged (e.g., JLP)
|
|
1053
1108
|
debtMint, // The asset provided initially by the user (e.g., USDC)
|
|
1054
1109
|
initialUserDebtContributionForSwap, // User's initial DEBT token for the swap
|
|
1055
|
-
targetLeverage, slippageBps) {
|
|
1110
|
+
targetLeverage, slippageBps, swapperOverride) {
|
|
1111
|
+
// override swapper if provided
|
|
1112
|
+
let activeSwapper = this.swapper;
|
|
1113
|
+
if (swapperOverride) {
|
|
1114
|
+
activeSwapper = swapperOverride;
|
|
1115
|
+
}
|
|
1056
1116
|
// 1. Get decimals and bank data
|
|
1057
1117
|
const collateralDecimals = (0, utils_1.getTokenDecimalsForMint)(collateralMint);
|
|
1058
1118
|
const debtDecimals = (0, utils_1.getTokenDecimalsForMint)(debtMint);
|
|
@@ -1083,12 +1143,18 @@ class ClendClient {
|
|
|
1083
1143
|
// This is the user's initial contribution + what's borrowed from the protocol
|
|
1084
1144
|
const totalDebtTokenForSwap = initialUserDebtContributionForSwap.add(finalLoopBorrowAmount);
|
|
1085
1145
|
// 7. Calculate Expected COLLATERAL Output from swapping the total DEBT token amount
|
|
1086
|
-
const swapQuote = await
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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
|
+
});
|
|
1090
1156
|
// Use the minimum amount threshold from the quote for safety in the final deposit instruction
|
|
1091
|
-
const expectedCollateralOutAmount = new anchor_1.BN(swapQuote.
|
|
1157
|
+
const expectedCollateralOutAmount = new anchor_1.BN(swapQuote.otherAmountThreshold);
|
|
1092
1158
|
// --- Logging ---
|
|
1093
1159
|
const finalLoopBorrowAmountUi = (0, clend_common_1.amountToUi)(finalLoopBorrowAmount, debtDecimals);
|
|
1094
1160
|
const totalDebtTokenForSwapUi = (0, clend_common_1.amountToUi)(totalDebtTokenForSwap, debtDecimals);
|
|
@@ -1117,19 +1183,19 @@ class ClendClient {
|
|
|
1117
1183
|
collateralBankData,
|
|
1118
1184
|
};
|
|
1119
1185
|
}
|
|
1120
|
-
async withdrawLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps) {
|
|
1186
|
+
async withdrawLeverage(clendGroup, clendAccount, selectedMint, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps, swapperOverride) {
|
|
1121
1187
|
let ixns = [];
|
|
1122
1188
|
let luts = [];
|
|
1123
1189
|
switch (selectedMint.toString()) {
|
|
1124
1190
|
case collateralMint.toString():
|
|
1125
|
-
const collateralParams = await this.getNetWithdrawLeverageCollateralParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps);
|
|
1126
|
-
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);
|
|
1127
1193
|
ixns = collateralIxns;
|
|
1128
1194
|
luts = collateralLuts;
|
|
1129
1195
|
break;
|
|
1130
1196
|
case debtMint.toString():
|
|
1131
|
-
const debtParams = await this.getNetWithdrawLeverageDebtParams(clendGroup, clendAccount, collateralMint, debtMint, withdrawAmount, withdrawAll, slippageBps);
|
|
1132
|
-
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);
|
|
1133
1199
|
ixns = debtIxns;
|
|
1134
1200
|
luts = debtLuts;
|
|
1135
1201
|
break;
|
|
@@ -1139,7 +1205,12 @@ class ClendClient {
|
|
|
1139
1205
|
// Send transaction
|
|
1140
1206
|
return this.send(ixns, [], luts);
|
|
1141
1207
|
}
|
|
1142
|
-
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
|
+
}
|
|
1143
1214
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1144
1215
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1145
1216
|
// Get remaining accounts for flash loan
|
|
@@ -1155,10 +1226,19 @@ class ClendClient {
|
|
|
1155
1226
|
}
|
|
1156
1227
|
const remainingAccounts = (0, utils_1.getClendAccountRemainingAccounts)(activeBankData);
|
|
1157
1228
|
// Get Jupiter quote for swapping collateral to debt token (ExactOut mode)
|
|
1158
|
-
const swapMode =
|
|
1159
|
-
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
|
+
});
|
|
1160
1240
|
// set collateralToSwap to the inAmount from the swap quote
|
|
1161
|
-
const collateralToSwap = swapQuote.
|
|
1241
|
+
const collateralToSwap = swapQuote.inAmount;
|
|
1162
1242
|
utils_1.logger.debug("withdrawLeverage collateralToSwap", {
|
|
1163
1243
|
collateralToSwap,
|
|
1164
1244
|
});
|
|
@@ -1171,7 +1251,7 @@ class ClendClient {
|
|
|
1171
1251
|
utils_1.logger.debug("withdrawLeverage swapInputs", {
|
|
1172
1252
|
swapInputs,
|
|
1173
1253
|
});
|
|
1174
|
-
const
|
|
1254
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1175
1255
|
utils_1.logger.info(`swapIxns fetched`);
|
|
1176
1256
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
1177
1257
|
const debtTokenProgram = (0, utils_1.getTokenProgramForMint)(debtMint);
|
|
@@ -1187,7 +1267,7 @@ class ClendClient {
|
|
|
1187
1267
|
// Assemble all instructions without flash loan
|
|
1188
1268
|
const ixnsWithoutFlashLoan = [
|
|
1189
1269
|
withdrawIx,
|
|
1190
|
-
...
|
|
1270
|
+
...swapIxns.ixns,
|
|
1191
1271
|
repayIx,
|
|
1192
1272
|
];
|
|
1193
1273
|
utils_1.logger.info(`ixnsWithoutFlashLoan set`);
|
|
@@ -1201,9 +1281,14 @@ class ClendClient {
|
|
|
1201
1281
|
...ixnsWithoutFlashLoan,
|
|
1202
1282
|
endFlashLoanIx,
|
|
1203
1283
|
];
|
|
1204
|
-
return { ixns: instructions, luts:
|
|
1284
|
+
return { ixns: instructions, luts: swapIxns.luts };
|
|
1205
1285
|
}
|
|
1206
|
-
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
|
+
}
|
|
1207
1292
|
const debtBank = (0, addresses_1.getBankPda)(clendGroup, debtMint);
|
|
1208
1293
|
const collateralBank = (0, addresses_1.getBankPda)(clendGroup, collateralMint);
|
|
1209
1294
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
@@ -1221,24 +1306,26 @@ class ClendClient {
|
|
|
1221
1306
|
// 1. Determine Total USDC Needed from the Swap
|
|
1222
1307
|
// This is the amount needed to repay Clend's debt AND give the user their desired net withdrawal.
|
|
1223
1308
|
const totalDebtToReceive = debtToRepay.add(desiredNetDebtToReceive);
|
|
1224
|
-
const swapMode =
|
|
1225
|
-
const swapQuote = await
|
|
1226
|
-
|
|
1227
|
-
|
|
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);
|
|
1228
1321
|
utils_1.logger.debug("getWithdrawLeverageDebtIxns: collateral and debt details", {
|
|
1229
1322
|
debtToRepay: debtToRepay.toString(),
|
|
1230
1323
|
desiredNetDebtToReceive: desiredNetDebtToReceive.toString(),
|
|
1231
1324
|
totalDebtToReceive: totalDebtToReceive.toString(),
|
|
1232
1325
|
minUsdcReceivedFromSwap_BN: minUsdcReceivedFromSwap_BN.toString(),
|
|
1233
1326
|
});
|
|
1234
|
-
// 3. Get Swap Instructions from
|
|
1235
|
-
|
|
1236
|
-
const swapInputs = {
|
|
1237
|
-
inputAmountLamports: new decimal_js_1.default(collateralToWithdraw.toString()),
|
|
1238
|
-
inputMint: collateralMint,
|
|
1239
|
-
outputMint: debtMint,
|
|
1240
|
-
};
|
|
1241
|
-
const jupiterSwapIxs = await this.getJupiterSwap(clendAccountData.authority, swapInputs, swapQuote);
|
|
1327
|
+
// 3. Get Swap Instructions from swapper
|
|
1328
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1242
1329
|
utils_1.logger.info(`swapIxns fetched for ReceiveDebtToken`);
|
|
1243
1330
|
// --- ATAs and Clend Instructions (largely similar structure) ---
|
|
1244
1331
|
const collateralTokenProgram = (0, utils_1.getTokenProgramForMint)(collateralMint);
|
|
@@ -1256,9 +1343,9 @@ class ClendClient {
|
|
|
1256
1343
|
// Assemble instructions
|
|
1257
1344
|
const ixnsWithoutFlashLoan = [
|
|
1258
1345
|
withdrawIx,
|
|
1259
|
-
...
|
|
1346
|
+
...swapIxns.ixns, // Swap all withdrawn collateral to debt
|
|
1260
1347
|
repayIx, // Repay the debt portion
|
|
1261
|
-
]; // User is left with the remaining
|
|
1348
|
+
]; // User is left with the remaining debt in their ATA
|
|
1262
1349
|
// Flash Loan Wrapping (same as before)
|
|
1263
1350
|
const cuIxns = 2;
|
|
1264
1351
|
const endIndex = new anchor_1.BN(cuIxns + ixnsWithoutFlashLoan.length + 1 + additionalIxnCount);
|
|
@@ -1268,11 +1355,16 @@ class ClendClient {
|
|
|
1268
1355
|
...ixnsWithoutFlashLoan,
|
|
1269
1356
|
endFlashLoanIx,
|
|
1270
1357
|
];
|
|
1271
|
-
return { ixns: instructions, luts:
|
|
1358
|
+
return { ixns: instructions, luts: swapIxns.luts };
|
|
1272
1359
|
}
|
|
1273
1360
|
// caller will receive desiredNetWithdraw, the position will be adjusted accordingly
|
|
1274
1361
|
// receive the collateral mint
|
|
1275
|
-
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
|
+
}
|
|
1276
1368
|
utils_1.logger.info("getNetWithdrawParams", {
|
|
1277
1369
|
desiredNetWithdraw: desiredNetWithdraw.toString(),
|
|
1278
1370
|
withdrawAll,
|
|
@@ -1360,11 +1452,17 @@ class ClendClient {
|
|
|
1360
1452
|
// --- Step 6: Get a Jupiter Quote for the Swap ---
|
|
1361
1453
|
// Query Jupiter for an EXACT_OUT swap to find out exactly how much collateral
|
|
1362
1454
|
// is needed to get the final amount of debt we need to repay.
|
|
1363
|
-
const swapQuote = await
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
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);
|
|
1368
1466
|
// --- Step 7: Calculate the Final Total Collateral to Withdraw ---
|
|
1369
1467
|
// This is the sum of what the user gets (desiredNetWithdraw) and what the swap needs.
|
|
1370
1468
|
collateralToWithdraw = desiredNetWithdraw.add(collateralNeededForSwap);
|
|
@@ -1386,7 +1484,12 @@ class ClendClient {
|
|
|
1386
1484
|
}
|
|
1387
1485
|
// caller will receive desiredNetWithdraw, the position will be adjusted accordingly
|
|
1388
1486
|
// receive the debt mint
|
|
1389
|
-
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
|
+
}
|
|
1390
1493
|
utils_1.logger.info("getNetWithdrawDebtParams", {
|
|
1391
1494
|
desiredNetWithdraw: desiredNetWithdraw.toString(),
|
|
1392
1495
|
withdrawAll,
|
|
@@ -1466,9 +1569,18 @@ class ClendClient {
|
|
|
1466
1569
|
// The total value we need to get from selling JLP is the debt we must repay
|
|
1467
1570
|
const totalDebtNeededFromSwap = debtToRepay.add(desiredNetWithdraw);
|
|
1468
1571
|
// Now, find how much collateral is needed to produce this swap via swap
|
|
1469
|
-
const swapQuote = await
|
|
1470
|
-
|
|
1471
|
-
|
|
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;
|
|
1472
1584
|
// --- Step 4: Final Sanity Check ---
|
|
1473
1585
|
if (collateralToWithdraw.gt(collateralAmount)) {
|
|
1474
1586
|
throw new Error("Total required collateral for withdrawal and swap exceeds the available balance.");
|
|
@@ -1485,9 +1597,9 @@ class ClendClient {
|
|
|
1485
1597
|
debtBankData,
|
|
1486
1598
|
};
|
|
1487
1599
|
}
|
|
1488
|
-
async adjustLeverage(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps) {
|
|
1600
|
+
async adjustLeverage(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps, swapperOverride) {
|
|
1489
1601
|
const params = await this.getAdjustLeverageParams(clendGroup, clendAccount, collateralMint, debtMint, targetLeverage, slippageBps);
|
|
1490
|
-
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);
|
|
1491
1603
|
// Send transaction
|
|
1492
1604
|
return this.send(ixns, [], luts);
|
|
1493
1605
|
}
|
|
@@ -1695,7 +1807,12 @@ class ClendClient {
|
|
|
1695
1807
|
*/
|
|
1696
1808
|
async getAdjustLeverageIxns(clendGroup, clendAccount, user, debtBankData, collateralBankData, isIncrease, finalDebtDeltaUi, // Use the final adjusted value from getAdjustLeverageParams
|
|
1697
1809
|
finalCollateralDeltaUi, // Use the final adjusted value from getAdjustLeverageParams
|
|
1698
|
-
slippageBps, additionalIxnCount) {
|
|
1810
|
+
slippageBps, additionalIxnCount, swapperOverride) {
|
|
1811
|
+
// override swapper if provided
|
|
1812
|
+
let activeSwapper = this.swapper;
|
|
1813
|
+
if (swapperOverride) {
|
|
1814
|
+
activeSwapper = swapperOverride;
|
|
1815
|
+
}
|
|
1699
1816
|
const clendAccountData = await this.getClendAccount(clendAccount);
|
|
1700
1817
|
if (!clendAccountData) {
|
|
1701
1818
|
throw new Error(`Clend account not found: ${clendAccount.toString()}`);
|
|
@@ -1730,34 +1847,37 @@ class ClendClient {
|
|
|
1730
1847
|
additionalDebtAmount: additionalDebtAmount.toString(),
|
|
1731
1848
|
});
|
|
1732
1849
|
// Get Jupiter quote for swapping debt token to collateral token (ExactIn)
|
|
1733
|
-
const swapMode =
|
|
1734
|
-
const swapQuote = await
|
|
1735
|
-
|
|
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
|
+
});
|
|
1736
1861
|
utils_1.logger.debug("swapQuote calculated (Increase)", {
|
|
1737
|
-
inAmount: swapQuote.
|
|
1738
|
-
outAmount: swapQuote.
|
|
1739
|
-
|
|
1862
|
+
inAmount: swapQuote.inAmount.toString(),
|
|
1863
|
+
outAmount: swapQuote.outAmount.toString(),
|
|
1864
|
+
otherAmountThreshold: swapQuote.otherAmountThreshold.toString(),
|
|
1740
1865
|
});
|
|
1741
1866
|
// Get swap instructions
|
|
1742
|
-
const
|
|
1743
|
-
inputAmountLamports: new decimal_js_1.default(additionalDebtAmount.toString()),
|
|
1744
|
-
inputMint: debtBankData.mint,
|
|
1745
|
-
outputMint: collateralBankData.mint,
|
|
1746
|
-
};
|
|
1747
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
1867
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1748
1868
|
// Borrow the final adjusted debt amount
|
|
1749
1869
|
const borrowIx = await this.instructions.borrow(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, additionalDebtAmount, // Use final adjusted amount
|
|
1750
1870
|
remainingAccounts);
|
|
1751
1871
|
// Calculate additional collateral expected from swap (based on quote)
|
|
1752
|
-
const additionalCollateralAmount =
|
|
1872
|
+
const additionalCollateralAmount = swapQuote.outAmount;
|
|
1753
1873
|
utils_1.logger.debug("additionalCollateralAmount expected from swap", {
|
|
1754
1874
|
additionalCollateralAmount: additionalCollateralAmount.toString(),
|
|
1755
1875
|
});
|
|
1756
1876
|
// Deposit additional collateral received from swap
|
|
1757
1877
|
const depositIx = await this.instructions.deposit(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, additionalCollateralAmount, // Deposit what the swap provides
|
|
1758
1878
|
true, remainingAccounts);
|
|
1759
|
-
instructions.push(borrowIx, ...
|
|
1760
|
-
swapLookupTables =
|
|
1879
|
+
instructions.push(borrowIx, ...swapIxns.ixns, depositIx);
|
|
1880
|
+
swapLookupTables = swapIxns.luts;
|
|
1761
1881
|
}
|
|
1762
1882
|
else {
|
|
1763
1883
|
// Decreasing Leverage
|
|
@@ -1772,22 +1892,24 @@ class ClendClient {
|
|
|
1772
1892
|
});
|
|
1773
1893
|
// Get Jupiter quote for swapping collateral token to debt token (ExactOut)
|
|
1774
1894
|
// Target the final buffered debt repayment amount
|
|
1775
|
-
const swapMode =
|
|
1776
|
-
const swapQuote = await
|
|
1777
|
-
|
|
1778
|
-
|
|
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;
|
|
1779
1907
|
utils_1.logger.debug("swapQuote calculated (Decrease)", {
|
|
1780
1908
|
targetOutput: finalDebtToRepayBN.toString(),
|
|
1781
1909
|
estimatedInput: estimatedCollateralInput,
|
|
1782
1910
|
maxInputCalculated: finalCollateralToWithdrawBN.toString(), // Compare Jupiter estimate vs our max calc
|
|
1783
|
-
priceImpactPct: swapQuote.quoteResponse.priceImpactPct,
|
|
1784
1911
|
});
|
|
1785
|
-
const
|
|
1786
|
-
inputAmountLamports: new decimal_js_1.default(swapQuote.quoteResponse.inAmount.toString()),
|
|
1787
|
-
inputMint: collateralBankData.mint,
|
|
1788
|
-
outputMint: debtBankData.mint,
|
|
1789
|
-
};
|
|
1790
|
-
const swapIxs = await this.getJupiterSwap(user, swapInputs, swapQuote);
|
|
1912
|
+
const swapIxns = await activeSwapper.getSwapIxns(swapQuote);
|
|
1791
1913
|
// Withdraw the CALCULATED MAXIMUM collateral needed (includes swap input + buffer)
|
|
1792
1914
|
const withdrawIx = await this.instructions.withdraw(clendGroup, clendAccount, user, collateralBankData.key, userCollateralAta, collateralTokenProgram, finalCollateralToWithdrawBN, // Use the final adjusted amount from params
|
|
1793
1915
|
false, // Not withdrawing all
|
|
@@ -1796,8 +1918,8 @@ class ClendClient {
|
|
|
1796
1918
|
const repayIx = await this.instructions.repay(clendGroup, clendAccount, user, debtBankData.key, userDebtAta, debtTokenProgram, finalDebtToRepayBN, // Use the final adjusted amount from params
|
|
1797
1919
|
false, // Not repaying all
|
|
1798
1920
|
remainingAccounts);
|
|
1799
|
-
instructions.push(withdrawIx, ...
|
|
1800
|
-
swapLookupTables =
|
|
1921
|
+
instructions.push(withdrawIx, ...swapIxns.ixns, repayIx);
|
|
1922
|
+
swapLookupTables = swapIxns.luts;
|
|
1801
1923
|
}
|
|
1802
1924
|
// --- Flash Loan Wrapping ---
|
|
1803
1925
|
const cuIxns = 2; // Assuming 2 compute budget instructions are added later
|