@haven-fi/solauto-sdk 1.0.581 → 1.0.583

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/dist/constants/solautoConstants.d.ts +1 -0
  2. package/dist/constants/solautoConstants.d.ts.map +1 -1
  3. package/dist/constants/solautoConstants.js +4 -10
  4. package/dist/constants/switchboardConstants.d.ts.map +1 -1
  5. package/dist/constants/switchboardConstants.js +5 -5
  6. package/dist/generated/accounts/solautoPosition.js +2 -2
  7. package/dist/generated/errors/solauto.d.ts +14 -2
  8. package/dist/generated/errors/solauto.d.ts.map +1 -1
  9. package/dist/generated/errors/solauto.js +27 -5
  10. package/dist/generated/instructions/claimReferralFees.d.ts +1 -1
  11. package/dist/generated/instructions/claimReferralFees.d.ts.map +1 -1
  12. package/dist/generated/instructions/closePosition.d.ts +1 -1
  13. package/dist/generated/instructions/closePosition.d.ts.map +1 -1
  14. package/dist/generated/instructions/closePosition.js +2 -2
  15. package/dist/generated/instructions/marginfiOpenPosition.d.ts +1 -3
  16. package/dist/generated/instructions/marginfiOpenPosition.d.ts.map +1 -1
  17. package/dist/generated/instructions/marginfiOpenPosition.js +0 -1
  18. package/dist/generated/instructions/marginfiRebalance.d.ts +7 -3
  19. package/dist/generated/instructions/marginfiRebalance.d.ts.map +1 -1
  20. package/dist/generated/instructions/marginfiRebalance.js +3 -1
  21. package/dist/generated/types/index.d.ts +7 -1
  22. package/dist/generated/types/index.d.ts.map +1 -1
  23. package/dist/generated/types/index.js +7 -1
  24. package/dist/generated/types/positionData.d.ts +2 -2
  25. package/dist/generated/types/positionData.d.ts.map +1 -1
  26. package/dist/generated/types/positionData.js +1 -1
  27. package/dist/generated/types/positionState.d.ts +7 -7
  28. package/dist/generated/types/positionState.d.ts.map +1 -1
  29. package/dist/generated/types/positionState.js +3 -3
  30. package/dist/generated/types/{positionTokenUsage.d.ts → positionTokenState.d.ts} +6 -8
  31. package/dist/generated/types/positionTokenState.d.ts.map +1 -0
  32. package/dist/generated/types/{positionTokenUsage.js → positionTokenState.js} +6 -7
  33. package/dist/generated/types/rebalanceData.d.ts +7 -13
  34. package/dist/generated/types/rebalanceData.d.ts.map +1 -1
  35. package/dist/generated/types/rebalanceData.js +3 -6
  36. package/dist/generated/types/rebalanceDirection.d.ts +3 -2
  37. package/dist/generated/types/rebalanceDirection.d.ts.map +1 -1
  38. package/dist/generated/types/rebalanceDirection.js +3 -2
  39. package/dist/generated/types/rebalanceInstructionData.d.ts +27 -0
  40. package/dist/generated/types/rebalanceInstructionData.d.ts.map +1 -0
  41. package/dist/generated/types/rebalanceInstructionData.js +22 -0
  42. package/dist/generated/types/rebalanceStateValues.d.ts +27 -0
  43. package/dist/generated/types/rebalanceStateValues.d.ts.map +1 -0
  44. package/dist/generated/types/rebalanceStateValues.js +22 -0
  45. package/dist/generated/types/rebalanceStep.d.ts +15 -0
  46. package/dist/generated/types/rebalanceStep.d.ts.map +1 -0
  47. package/dist/generated/types/rebalanceStep.js +22 -0
  48. package/dist/generated/types/solautoRebalanceType.d.ts +4 -5
  49. package/dist/generated/types/solautoRebalanceType.d.ts.map +1 -1
  50. package/dist/generated/types/solautoRebalanceType.js +4 -5
  51. package/dist/generated/types/solautoSettingsParameters.d.ts +2 -15
  52. package/dist/generated/types/solautoSettingsParameters.d.ts.map +1 -1
  53. package/dist/generated/types/solautoSettingsParameters.js +1 -5
  54. package/dist/generated/types/solautoSettingsParametersInp.d.ts +1 -12
  55. package/dist/generated/types/solautoSettingsParametersInp.d.ts.map +1 -1
  56. package/dist/generated/types/solautoSettingsParametersInp.js +0 -3
  57. package/dist/generated/types/swapType.d.ts +15 -0
  58. package/dist/generated/types/swapType.d.ts.map +1 -0
  59. package/dist/generated/types/swapType.js +22 -0
  60. package/dist/generated/types/tokenBalanceChange.d.ts +21 -0
  61. package/dist/generated/types/tokenBalanceChange.d.ts.map +1 -0
  62. package/dist/generated/types/tokenBalanceChange.js +19 -0
  63. package/dist/generated/types/tokenBalanceChangeType.d.ts +18 -0
  64. package/dist/generated/types/tokenBalanceChangeType.d.ts.map +1 -0
  65. package/dist/generated/types/tokenBalanceChangeType.js +25 -0
  66. package/dist/generated/types/updatePositionData.d.ts +2 -2
  67. package/dist/generated/types/updatePositionData.d.ts.map +1 -1
  68. package/dist/generated/types/updatePositionData.js +1 -1
  69. package/dist/index.d.ts +8 -6
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +5 -5
  72. package/dist/marginfi-sdk/types/interestRateConfig.d.ts +3 -1
  73. package/dist/marginfi-sdk/types/interestRateConfig.d.ts.map +1 -1
  74. package/dist/marginfi-sdk/types/interestRateConfig.js +2 -1
  75. package/dist/services/flashLoans/flProviderAggregator.d.ts +19 -0
  76. package/dist/services/flashLoans/flProviderAggregator.d.ts.map +1 -0
  77. package/dist/services/flashLoans/flProviderAggregator.js +46 -0
  78. package/dist/services/flashLoans/flProviderBase.d.ts +23 -0
  79. package/dist/services/flashLoans/flProviderBase.d.ts.map +1 -0
  80. package/dist/services/flashLoans/flProviderBase.js +37 -0
  81. package/dist/services/flashLoans/index.d.ts +4 -0
  82. package/dist/services/flashLoans/index.d.ts.map +1 -0
  83. package/dist/services/flashLoans/index.js +19 -0
  84. package/dist/services/flashLoans/marginfiFlProvider.d.ts +25 -0
  85. package/dist/services/flashLoans/marginfiFlProvider.d.ts.map +1 -0
  86. package/dist/services/flashLoans/marginfiFlProvider.js +246 -0
  87. package/dist/services/index.d.ts +6 -0
  88. package/dist/services/index.d.ts.map +1 -0
  89. package/dist/services/index.js +21 -0
  90. package/dist/services/rebalance/index.d.ts +3 -0
  91. package/dist/services/rebalance/index.d.ts.map +1 -0
  92. package/dist/services/rebalance/index.js +18 -0
  93. package/dist/services/rebalance/rebalanceSwapManager.d.ts +30 -0
  94. package/dist/services/rebalance/rebalanceSwapManager.d.ts.map +1 -0
  95. package/dist/services/rebalance/rebalanceSwapManager.js +144 -0
  96. package/dist/services/rebalance/rebalanceTxBuilder.d.ts +22 -0
  97. package/dist/services/rebalance/rebalanceTxBuilder.d.ts.map +1 -0
  98. package/dist/services/rebalance/rebalanceTxBuilder.js +200 -0
  99. package/dist/services/rebalance/rebalanceValues.d.ts +31 -0
  100. package/dist/services/rebalance/rebalanceValues.d.ts.map +1 -0
  101. package/dist/services/rebalance/rebalanceValues.js +118 -0
  102. package/dist/services/rebalance/solautoFees.d.ts +13 -0
  103. package/dist/services/rebalance/solautoFees.d.ts.map +1 -0
  104. package/dist/services/rebalance/solautoFees.js +54 -0
  105. package/dist/services/solauto/index.d.ts +5 -0
  106. package/dist/services/solauto/index.d.ts.map +1 -0
  107. package/dist/{clients → services/solauto}/referralStateManager.d.ts +4 -5
  108. package/dist/services/solauto/referralStateManager.d.ts.map +1 -0
  109. package/dist/{clients → services/solauto}/referralStateManager.js +10 -12
  110. package/dist/services/solauto/solautoClient.d.ts +59 -0
  111. package/dist/services/solauto/solautoClient.d.ts.map +1 -0
  112. package/dist/{clients → services/solauto}/solautoClient.js +78 -109
  113. package/dist/services/solauto/solautoMarginfiClient.d.ts +34 -0
  114. package/dist/services/solauto/solautoMarginfiClient.d.ts.map +1 -0
  115. package/dist/services/solauto/solautoMarginfiClient.js +322 -0
  116. package/dist/{clients → services/solauto}/txHandler.d.ts +11 -2
  117. package/dist/services/solauto/txHandler.d.ts.map +1 -0
  118. package/dist/services/solauto/txHandler.js +38 -0
  119. package/dist/services/swap/index.d.ts +2 -0
  120. package/dist/services/swap/index.d.ts.map +1 -0
  121. package/dist/{utils/solauto → services/swap}/index.js +1 -2
  122. package/dist/services/swap/jupSwapManager.d.ts +37 -0
  123. package/dist/services/swap/jupSwapManager.d.ts.map +1 -0
  124. package/dist/services/swap/jupSwapManager.js +108 -0
  125. package/dist/services/transactions/index.d.ts.map +1 -0
  126. package/dist/{transactions → services/transactions}/transactionUtils.d.ts +3 -5
  127. package/dist/services/transactions/transactionUtils.d.ts.map +1 -0
  128. package/dist/{transactions → services/transactions}/transactionUtils.js +29 -137
  129. package/dist/{transactions → services/transactions}/transactionsManager.d.ts +4 -4
  130. package/dist/services/transactions/transactionsManager.d.ts.map +1 -0
  131. package/dist/{transactions → services/transactions}/transactionsManager.js +10 -8
  132. package/dist/solautoPosition/index.d.ts +4 -0
  133. package/dist/solautoPosition/index.d.ts.map +1 -0
  134. package/dist/solautoPosition/index.js +19 -0
  135. package/dist/solautoPosition/marginfiSolautoPositionEx.d.ts +14 -0
  136. package/dist/solautoPosition/marginfiSolautoPositionEx.d.ts.map +1 -0
  137. package/dist/solautoPosition/marginfiSolautoPositionEx.js +73 -0
  138. package/dist/solautoPosition/solautoPositionEx.d.ts +67 -0
  139. package/dist/solautoPosition/solautoPositionEx.d.ts.map +1 -0
  140. package/dist/solautoPosition/solautoPositionEx.js +143 -0
  141. package/dist/solautoPosition/utils.d.ts +17 -0
  142. package/dist/solautoPosition/utils.d.ts.map +1 -0
  143. package/dist/solautoPosition/utils.js +115 -0
  144. package/dist/types/solauto.d.ts +19 -1
  145. package/dist/types/solauto.d.ts.map +1 -1
  146. package/dist/utils/generalUtils.d.ts +1 -0
  147. package/dist/utils/generalUtils.d.ts.map +1 -1
  148. package/dist/utils/generalUtils.js +9 -1
  149. package/dist/utils/index.d.ts +1 -1
  150. package/dist/utils/index.d.ts.map +1 -1
  151. package/dist/utils/index.js +1 -1
  152. package/dist/utils/jitoUtils.d.ts.map +1 -1
  153. package/dist/utils/jupiterUtils.d.ts +3 -28
  154. package/dist/utils/jupiterUtils.d.ts.map +1 -1
  155. package/dist/utils/jupiterUtils.js +2 -73
  156. package/dist/utils/marginfiUtils.d.ts +4 -3
  157. package/dist/utils/marginfiUtils.d.ts.map +1 -1
  158. package/dist/utils/marginfiUtils.js +47 -18
  159. package/dist/utils/numberUtils.d.ts +3 -6
  160. package/dist/utils/numberUtils.d.ts.map +1 -1
  161. package/dist/utils/numberUtils.js +13 -48
  162. package/dist/utils/priceUtils.js +1 -1
  163. package/dist/utils/solanaUtils.js +2 -2
  164. package/dist/utils/{solauto/generalUtils.d.ts → solautoUtils.d.ts} +9 -16
  165. package/dist/utils/solautoUtils.d.ts.map +1 -0
  166. package/dist/utils/{solauto/generalUtils.js → solautoUtils.js} +48 -173
  167. package/dist/utils/switchboardUtils.d.ts +1 -1
  168. package/dist/utils/switchboardUtils.d.ts.map +1 -1
  169. package/dist/utils/switchboardUtils.js +10 -9
  170. package/local/createTokenAccounts.ts +1 -5
  171. package/local/logPositions.ts +22 -68
  172. package/local/shared.ts +29 -24
  173. package/local/txSandbox.ts +27 -0
  174. package/local/updateMarginfiLUT.ts +80 -4
  175. package/package.json +4 -7
  176. package/src/constants/solautoConstants.ts +4 -9
  177. package/src/constants/switchboardConstants.ts +10 -5
  178. package/src/generated/accounts/solautoPosition.ts +2 -2
  179. package/src/generated/errors/solauto.ts +45 -4
  180. package/src/generated/instructions/claimReferralFees.ts +1 -1
  181. package/src/generated/instructions/closePosition.ts +3 -3
  182. package/src/generated/instructions/marginfiOpenPosition.ts +0 -7
  183. package/src/generated/instructions/marginfiRebalance.ts +12 -3
  184. package/src/generated/types/index.ts +7 -1
  185. package/src/generated/types/positionData.ts +3 -3
  186. package/src/generated/types/positionState.ts +12 -12
  187. package/src/generated/types/{positionTokenUsage.ts → positionTokenState.ts} +13 -16
  188. package/src/generated/types/rebalanceData.ts +16 -27
  189. package/src/generated/types/rebalanceDirection.ts +1 -0
  190. package/src/generated/types/rebalanceInstructionData.ts +62 -0
  191. package/src/generated/types/rebalanceStateValues.ts +59 -0
  192. package/src/generated/types/rebalanceStep.ts +25 -0
  193. package/src/generated/types/solautoRebalanceType.ts +0 -1
  194. package/src/generated/types/solautoSettingsParameters.ts +4 -25
  195. package/src/generated/types/solautoSettingsParametersInp.ts +2 -24
  196. package/src/generated/types/swapType.ts +22 -0
  197. package/src/generated/types/tokenBalanceChange.ts +46 -0
  198. package/src/generated/types/tokenBalanceChangeType.ts +28 -0
  199. package/src/generated/types/updatePositionData.ts +3 -3
  200. package/src/index.ts +8 -8
  201. package/src/marginfi-sdk/types/interestRateConfig.ts +6 -2
  202. package/src/services/flashLoans/flProviderAggregator.ts +74 -0
  203. package/src/services/flashLoans/flProviderBase.ts +88 -0
  204. package/src/services/flashLoans/index.ts +3 -0
  205. package/src/services/flashLoans/marginfiFlProvider.ts +392 -0
  206. package/src/services/index.ts +5 -0
  207. package/src/services/rebalance/index.ts +2 -0
  208. package/src/services/rebalance/rebalanceSwapManager.ts +218 -0
  209. package/src/services/rebalance/rebalanceTxBuilder.ts +330 -0
  210. package/src/services/rebalance/rebalanceValues.ts +232 -0
  211. package/src/services/rebalance/solautoFees.ts +61 -0
  212. package/src/services/solauto/index.ts +4 -0
  213. package/src/{clients → services/solauto}/referralStateManager.ts +17 -31
  214. package/src/{clients → services/solauto}/solautoClient.ts +142 -205
  215. package/src/services/solauto/solautoMarginfiClient.ts +472 -0
  216. package/src/services/solauto/txHandler.ts +69 -0
  217. package/src/services/swap/index.ts +1 -0
  218. package/src/services/swap/jupSwapManager.ts +189 -0
  219. package/src/{transactions → services/transactions}/transactionUtils.ts +40 -280
  220. package/src/{transactions → services/transactions}/transactionsManager.ts +15 -10
  221. package/src/solautoPosition/index.ts +3 -0
  222. package/src/solautoPosition/marginfiSolautoPositionEx.ts +111 -0
  223. package/src/solautoPosition/solautoPositionEx.ts +281 -0
  224. package/src/solautoPosition/utils.ts +188 -0
  225. package/src/types/solauto.ts +30 -2
  226. package/src/utils/generalUtils.ts +9 -1
  227. package/src/utils/index.ts +2 -2
  228. package/src/utils/jitoUtils.ts +0 -4
  229. package/src/utils/jupiterUtils.ts +3 -164
  230. package/src/utils/marginfiUtils.ts +77 -43
  231. package/src/utils/numberUtils.ts +18 -77
  232. package/src/utils/solanaUtils.ts +1 -1
  233. package/src/utils/{solauto/generalUtils.ts → solautoUtils.ts} +66 -288
  234. package/src/utils/switchboardUtils.ts +15 -17
  235. package/tests/transactions/shared.ts +135 -0
  236. package/tests/transactions/solautoMarginfi.ts +8 -198
  237. package/tests/unit/accounts.ts +3 -10
  238. package/tests/unit/lookupTables.ts +23 -2
  239. package/tests/unit/rebalanceCalculations.ts +65 -343
  240. package/dist/clients/index.d.ts +0 -5
  241. package/dist/clients/index.d.ts.map +0 -1
  242. package/dist/clients/referralStateManager.d.ts.map +0 -1
  243. package/dist/clients/solautoClient.d.ts +0 -71
  244. package/dist/clients/solautoClient.d.ts.map +0 -1
  245. package/dist/clients/solautoMarginfiClient.d.ts +0 -51
  246. package/dist/clients/solautoMarginfiClient.d.ts.map +0 -1
  247. package/dist/clients/solautoMarginfiClient.js +0 -497
  248. package/dist/clients/txHandler.d.ts.map +0 -1
  249. package/dist/clients/txHandler.js +0 -23
  250. package/dist/generated/types/positionTokenUsage.d.ts.map +0 -1
  251. package/dist/transactions/index.d.ts.map +0 -1
  252. package/dist/transactions/transactionUtils.d.ts.map +0 -1
  253. package/dist/transactions/transactionsManager.d.ts.map +0 -1
  254. package/dist/utils/solauto/generalUtils.d.ts.map +0 -1
  255. package/dist/utils/solauto/index.d.ts +0 -3
  256. package/dist/utils/solauto/index.d.ts.map +0 -1
  257. package/dist/utils/solauto/rebalanceUtils.d.ts +0 -30
  258. package/dist/utils/solauto/rebalanceUtils.d.ts.map +0 -1
  259. package/dist/utils/solauto/rebalanceUtils.js +0 -287
  260. package/src/clients/index.ts +0 -4
  261. package/src/clients/solautoMarginfiClient.ts +0 -774
  262. package/src/clients/txHandler.ts +0 -38
  263. package/src/utils/solauto/index.ts +0 -2
  264. package/src/utils/solauto/rebalanceUtils.ts +0 -562
  265. package/dist/{clients → services/solauto}/index.js +2 -2
  266. /package/dist/{transactions → services/transactions}/index.d.ts +0 -0
  267. /package/dist/{transactions → services/transactions}/index.js +0 -0
  268. /package/src/{transactions → services/transactions}/index.ts +0 -0
@@ -0,0 +1,218 @@
1
+ import { QuoteResponse } from "@jup-ag/api";
2
+ import { FlashLoanRequirements } from "../../types";
3
+ import { SolautoClient } from "../solauto";
4
+ import { JupSwapManager, SwapParams, SwapInput } from "../swap";
5
+ import { RebalanceValues } from "./rebalanceValues";
6
+ import { RebalanceDirection, TokenType } from "../../generated";
7
+ import {
8
+ consoleLog,
9
+ fromBaseUnit,
10
+ getLiqUtilzationRateBps,
11
+ maxRepayToBps,
12
+ safeGetPrice,
13
+ toBaseUnit,
14
+ tokenInfo,
15
+ } from "../../utils";
16
+ import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
17
+
18
+ export class RebalanceSwapManager {
19
+ public swapParams!: SwapParams;
20
+ public swapQuote?: QuoteResponse;
21
+ public flBorrowAmount?: bigint;
22
+
23
+ private jupSwapManager!: JupSwapManager;
24
+
25
+ constructor(
26
+ private client: SolautoClient,
27
+ private values: RebalanceValues,
28
+ private flRequirements?: FlashLoanRequirements,
29
+ private targetLiqUtilizationRateBps?: number
30
+ ) {
31
+ this.jupSwapManager = new JupSwapManager(client.signer);
32
+ }
33
+
34
+ private isBoost() {
35
+ return this.values.rebalanceDirection === RebalanceDirection.Boost;
36
+ }
37
+
38
+ private usdToSwap() {
39
+ return Math.abs(this.values.debtAdjustmentUsd);
40
+ }
41
+
42
+ private postRebalanceLiqUtilizationRateBps(swapOutputAmount?: bigint) {
43
+ let supplyUsd = this.client.solautoPosition.supplyUsd();
44
+ // TODO: add token balance change
45
+ let debtUsd = this.client.solautoPosition.debtUsd();
46
+
47
+ const outputToken = toWeb3JsPublicKey(
48
+ this.isBoost()
49
+ ? this.client.solautoPosition.state().supply.mint
50
+ : this.client.solautoPosition.state().debt.mint
51
+ );
52
+ const swapOutputUsd = swapOutputAmount
53
+ ? fromBaseUnit(swapOutputAmount, tokenInfo(outputToken).decimals) *
54
+ (safeGetPrice(outputToken) ?? 0)
55
+ : this.usdToSwap();
56
+
57
+ supplyUsd = this.isBoost()
58
+ ? supplyUsd + swapOutputUsd
59
+ : supplyUsd - this.usdToSwap();
60
+ debtUsd = this.isBoost()
61
+ ? debtUsd + this.usdToSwap()
62
+ : debtUsd - swapOutputUsd;
63
+
64
+ return getLiqUtilzationRateBps(
65
+ supplyUsd,
66
+ debtUsd,
67
+ this.client.solautoPosition.state().liqThresholdBps ?? 0
68
+ );
69
+ }
70
+
71
+ private async findSufficientQuote(
72
+ swapInput: SwapInput,
73
+ criteria: {
74
+ minOutputAmount?: bigint;
75
+ minLiqUtilizationRateBps?: number;
76
+ maxLiqUtilizationRateBps?: number;
77
+ }
78
+ ): Promise<QuoteResponse> {
79
+ let swapQuote: QuoteResponse;
80
+ let insufficient: boolean = false;
81
+
82
+ for (let i = 0; i < 10; i++) {
83
+ consoleLog("Finding sufficient quote...");
84
+ swapQuote = await this.jupSwapManager.getQuote(swapInput);
85
+
86
+ const outputAmount = parseInt(swapQuote.outAmount);
87
+ const postRebalanceRate = this.postRebalanceLiqUtilizationRateBps(
88
+ BigInt(outputAmount)
89
+ );
90
+ insufficient = criteria.minOutputAmount
91
+ ? outputAmount < Number(criteria.minOutputAmount)
92
+ : criteria.minLiqUtilizationRateBps
93
+ ? postRebalanceRate < criteria.minLiqUtilizationRateBps
94
+ : postRebalanceRate > criteria.maxLiqUtilizationRateBps!;
95
+
96
+ if (insufficient) {
97
+ consoleLog("Insufficient swap quote:", swapQuote);
98
+ swapInput.amount = this.bigIntWithIncrement(swapInput.amount, 0.01);
99
+ } else {
100
+ break;
101
+ }
102
+ }
103
+
104
+ return swapQuote!;
105
+ }
106
+
107
+ private swapDetails() {
108
+ const input = this.isBoost()
109
+ ? this.client.solautoPosition.state().debt
110
+ : this.client.solautoPosition.state().supply;
111
+ const output = this.isBoost()
112
+ ? this.client.solautoPosition.state().supply
113
+ : this.client.solautoPosition.state().debt;
114
+
115
+ let inputAmount = toBaseUnit(
116
+ this.usdToSwap() / safeGetPrice(input.mint)!,
117
+ input.decimals
118
+ );
119
+
120
+ return {
121
+ input,
122
+ output,
123
+ inputAmount,
124
+ };
125
+ }
126
+
127
+ private bigIntWithIncrement(num: bigint, inc: number) {
128
+ return num + BigInt(Math.round(Number(num) * inc));
129
+ }
130
+
131
+ async setSwapParams(attemptNum: number) {
132
+ const rebalanceToZero = this.targetLiqUtilizationRateBps === 0;
133
+ let { input, output, inputAmount } = this.swapDetails();
134
+
135
+ let outputAmount = rebalanceToZero
136
+ ? output.amountUsed.baseUnit +
137
+ BigInt(
138
+ Math.round(
139
+ Number(output.amountUsed.baseUnit) *
140
+ // Add this small percentage to account for the APR on the debt between now and the transaction
141
+ 0.0001
142
+ )
143
+ )
144
+ : toBaseUnit(
145
+ this.usdToSwap() / safeGetPrice(output.mint)!,
146
+ output.decimals
147
+ );
148
+
149
+ const flashLoanRepayFromDebt =
150
+ !this.isBoost() &&
151
+ this.flRequirements &&
152
+ this.flRequirements.liquiditySource === TokenType.Debt;
153
+
154
+ const exactOut = flashLoanRepayFromDebt && !rebalanceToZero;
155
+ const exactIn = !exactOut;
156
+
157
+ if (exactIn && (rebalanceToZero || this.values.repayingCloseToMaxLtv)) {
158
+ inputAmount = this.bigIntWithIncrement(inputAmount, 0.005);
159
+ }
160
+
161
+ const swapAmount = exactOut
162
+ ? this.flRequirements
163
+ ? this.bigIntWithIncrement(
164
+ outputAmount,
165
+ this.flRequirements.flFeeBps ?? 0
166
+ )
167
+ : outputAmount
168
+ : inputAmount;
169
+ const swapInput: SwapInput = {
170
+ inputMint: toWeb3JsPublicKey(input.mint),
171
+ outputMint: toWeb3JsPublicKey(output.mint),
172
+ exactIn,
173
+ exactOut,
174
+ amount: swapAmount,
175
+ };
176
+ consoleLog("Swap input:", swapInput);
177
+
178
+ if (exactIn && (rebalanceToZero || this.values.repayingCloseToMaxLtv)) {
179
+ this.swapQuote = await this.findSufficientQuote(swapInput, {
180
+ minOutputAmount: rebalanceToZero ? outputAmount : undefined,
181
+ maxLiqUtilizationRateBps: this.values.repayingCloseToMaxLtv
182
+ ? maxRepayToBps(
183
+ this.client.solautoPosition.state().maxLtvBps ?? 0,
184
+ this.client.solautoPosition.state().liqThresholdBps ?? 0
185
+ ) - 15
186
+ : undefined,
187
+ });
188
+ }
189
+
190
+ if (this.flRequirements) {
191
+ this.flBorrowAmount = exactOut
192
+ ? outputAmount
193
+ : this.swapQuote
194
+ ? BigInt(parseInt(this.swapQuote.inAmount))
195
+ : inputAmount;
196
+ }
197
+
198
+ this.swapParams = {
199
+ ...swapInput,
200
+ destinationWallet: flashLoanRepayFromDebt
201
+ ? toWeb3JsPublicKey(this.client.signer.publicKey)
202
+ : this.client.solautoPosition.publicKey,
203
+ slippageIncFactor: 0.2 + attemptNum * 0.25,
204
+ };
205
+ }
206
+
207
+ async getSwapTxData() {
208
+ const { jupQuote, lookupTableAddresses, setupInstructions, swapIx } =
209
+ await this.jupSwapManager.getJupSwapTxData(this.swapParams);
210
+
211
+ return {
212
+ swapQuote: jupQuote,
213
+ lookupTableAddresses,
214
+ setupInstructions,
215
+ swapIx,
216
+ };
217
+ }
218
+ }
@@ -0,0 +1,330 @@
1
+ import { SolautoClient } from "../solauto";
2
+ import {
3
+ FlashLoanRequirements,
4
+ RebalanceDetails,
5
+ TransactionItemInputs,
6
+ } from "../../types";
7
+ import {
8
+ consoleLog,
9
+ fromBaseUnit,
10
+ getMaxLiqUtilizationRateBps,
11
+ getTokenAccount,
12
+ hasFirstRebalance,
13
+ hasLastRebalance,
14
+ safeGetPrice,
15
+ tokenInfo,
16
+ } from "../../utils";
17
+ import { getRebalanceValues, RebalanceValues } from "./rebalanceValues";
18
+ import { SolautoFeesBps } from "./solautoFees";
19
+ import {
20
+ PositionTokenState,
21
+ RebalanceDirection,
22
+ RebalanceStep,
23
+ SolautoRebalanceType,
24
+ SwapType,
25
+ TokenBalanceChangeType,
26
+ TokenType,
27
+ } from "../../generated";
28
+ import { PublicKey } from "@solana/web3.js";
29
+ import { RebalanceSwapManager } from "./rebalanceSwapManager";
30
+ import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
31
+ import { transactionBuilder } from "@metaplex-foundation/umi";
32
+
33
+ export class RebalanceTxBuilder {
34
+ private values!: RebalanceValues;
35
+ private rebalanceType!: SolautoRebalanceType;
36
+ private swapManager!: RebalanceSwapManager;
37
+ private flRequirements?: FlashLoanRequirements;
38
+
39
+ constructor(
40
+ private client: SolautoClient,
41
+ private targetLiqUtilizationRateBps?: number
42
+ ) {}
43
+
44
+ private async shouldProceedWithRebalance() {
45
+ return (
46
+ this.client.solautoPosition.supplyUsd() > 0 &&
47
+ (this.targetLiqUtilizationRateBps !== undefined ||
48
+ this.client.solautoPosition.eligibleForRebalance())
49
+ );
50
+ }
51
+
52
+ private getRebalanceValues(flFee?: number) {
53
+ return getRebalanceValues(
54
+ this.client.solautoPosition,
55
+ new SolautoFeesBps(
56
+ this.client.isReferred(),
57
+ this.targetLiqUtilizationRateBps,
58
+ this.client.solautoPosition.netWorthUsd()
59
+ ),
60
+ flFee ?? 0,
61
+ this.targetLiqUtilizationRateBps
62
+ );
63
+ }
64
+
65
+ private getFlLiquiditySource(
66
+ supplyLiquidityAvailable: bigint,
67
+ debtLiquidityAvailable: bigint
68
+ ): TokenType | undefined {
69
+ const debtAdjustmentUsd = Math.abs(this.values.debtAdjustmentUsd);
70
+
71
+ const insufficientLiquidity = (
72
+ amountNeededUsd: number,
73
+ liquidityAvailable: bigint,
74
+ tokenMint: PublicKey
75
+ ) => {
76
+ return (
77
+ amountNeededUsd >
78
+ fromBaseUnit(liquidityAvailable, tokenInfo(tokenMint).decimals) *
79
+ (safeGetPrice(tokenMint) ?? 0) *
80
+ 0.95
81
+ );
82
+ };
83
+
84
+ const insufficientSupplyLiquidity = insufficientLiquidity(
85
+ debtAdjustmentUsd,
86
+ supplyLiquidityAvailable,
87
+ this.client.solautoPosition.supplyMint()
88
+ );
89
+ const insufficientDebtLiquidity = insufficientLiquidity(
90
+ debtAdjustmentUsd,
91
+ debtLiquidityAvailable,
92
+ this.client.solautoPosition.debtMint()
93
+ );
94
+
95
+ let useDebtLiquidity =
96
+ this.values.rebalanceDirection === RebalanceDirection.Boost ||
97
+ insufficientSupplyLiquidity;
98
+
99
+ if (useDebtLiquidity) {
100
+ return !insufficientDebtLiquidity ? TokenType.Debt : undefined;
101
+ } else {
102
+ return !insufficientSupplyLiquidity ? TokenType.Supply : undefined;
103
+ }
104
+ }
105
+
106
+ private async flashLoanRequirements(
107
+ attemptNum: number
108
+ ): Promise<FlashLoanRequirements | undefined> {
109
+ const maxLtvRateBps = getMaxLiqUtilizationRateBps(
110
+ this.client.solautoPosition.state().maxLtvBps,
111
+ this.client.solautoPosition.state().liqThresholdBps,
112
+ 0.02
113
+ );
114
+
115
+ if (this.values.intermediaryLiqUtilizationRateBps < maxLtvRateBps) {
116
+ return undefined;
117
+ }
118
+
119
+ const stdFlLiquiditySource = this.getFlLiquiditySource(
120
+ this.client.flProvider.liquidityAvailable(TokenType.Supply),
121
+ this.client.flProvider.liquidityAvailable(TokenType.Debt)
122
+ );
123
+
124
+ if ((attemptNum ?? 0) >= 3 || stdFlLiquiditySource === undefined) {
125
+ const { supplyBalance, debtBalance } = await this.client.signerBalances();
126
+ const signerFlLiquiditySource = this.getFlLiquiditySource(
127
+ supplyBalance,
128
+ debtBalance
129
+ );
130
+
131
+ if (signerFlLiquiditySource) {
132
+ return {
133
+ liquiditySource: signerFlLiquiditySource,
134
+ signerFlashLoan: true,
135
+ };
136
+ } else {
137
+ throw new Error(`Insufficient liquidity to perform the transaction`);
138
+ }
139
+ } else {
140
+ return {
141
+ liquiditySource: stdFlLiquiditySource,
142
+ flFeeBps: this.client.flProvider.flFeeBps(stdFlLiquiditySource),
143
+ };
144
+ }
145
+ }
146
+
147
+ private getFlashLoanDetails() {
148
+ if (!this.flRequirements) {
149
+ throw new Error("Flash loan requirements data needed");
150
+ }
151
+
152
+ const boosting =
153
+ this.values.rebalanceDirection === RebalanceDirection.Boost;
154
+ const useDebtLiquidity =
155
+ this.flRequirements.liquiditySource === TokenType.Debt;
156
+
157
+ let flashLoanToken: PositionTokenState | undefined = undefined;
158
+ if (boosting || useDebtLiquidity) {
159
+ flashLoanToken = this.client.solautoPosition.state().debt;
160
+ } else {
161
+ flashLoanToken = this.client.solautoPosition.state().supply;
162
+ }
163
+
164
+ return {
165
+ ...this.flRequirements,
166
+ baseUnitAmount: this.swapManager.flBorrowAmount!,
167
+ mint: toWeb3JsPublicKey(flashLoanToken.mint),
168
+ };
169
+ }
170
+
171
+ private setRebalanceType() {
172
+ if (this.flRequirements) {
173
+ const tokenBalanceChangeType = this.values.tokenBalanceChange?.changeType;
174
+ const firstRebalanceTokenChanges =
175
+ tokenBalanceChangeType === TokenBalanceChangeType.PreSwapDeposit;
176
+ const lastRebalanceTokenChanges = [
177
+ TokenBalanceChangeType.PostSwapDeposit,
178
+ TokenBalanceChangeType.PostRebalanceWithdrawDebtToken,
179
+ TokenBalanceChangeType.PostRebalanceWithdrawSupplyToken,
180
+ ].includes(tokenBalanceChangeType ?? TokenBalanceChangeType.None);
181
+
182
+ const swapType = this.swapManager.swapParams.exactIn
183
+ ? SwapType.ExactIn
184
+ : SwapType.ExactOut;
185
+
186
+ if (
187
+ (firstRebalanceTokenChanges && swapType === SwapType.ExactIn) ||
188
+ (lastRebalanceTokenChanges && swapType === SwapType.ExactOut)
189
+ ) {
190
+ this.rebalanceType = SolautoRebalanceType.DoubleRebalanceWithFL;
191
+ } else {
192
+ this.rebalanceType =
193
+ swapType === SwapType.ExactOut
194
+ ? SolautoRebalanceType.FLRebalanceThenSwap
195
+ : SolautoRebalanceType.FLSwapThenRebalance;
196
+ }
197
+ } else {
198
+ this.rebalanceType = SolautoRebalanceType.Regular;
199
+ }
200
+ consoleLog("Rebalance type:", this.rebalanceType);
201
+ }
202
+
203
+ private async setRebalanceDetails(attemptNum: number) {
204
+ this.values = this.getRebalanceValues();
205
+ this.flRequirements = await this.flashLoanRequirements(attemptNum);
206
+
207
+ if (this.flRequirements?.flFeeBps) {
208
+ this.values = this.getRebalanceValues(this.flRequirements.flFeeBps);
209
+ }
210
+
211
+ consoleLog("Rebalance values:", this.values);
212
+ this.swapManager = new RebalanceSwapManager(
213
+ this.client,
214
+ this.values,
215
+ this.flRequirements,
216
+ this.targetLiqUtilizationRateBps
217
+ );
218
+ await this.swapManager.setSwapParams(attemptNum);
219
+
220
+ this.setRebalanceType();
221
+ }
222
+
223
+ private async refreshBeforeRebalance() {
224
+ if (
225
+ this.client.selfManaged ||
226
+ this.client.contextUpdates.supplyAdjustment > BigInt(0) ||
227
+ this.client.contextUpdates.debtAdjustment > BigInt(0)
228
+ ) {
229
+ return false;
230
+ }
231
+ // Rebalance ix will already refresh internally if position is self managed
232
+
233
+ if (!this.client.solautoPosition.data().position) {
234
+ return true;
235
+ }
236
+
237
+ const utilizationRateDiff = Math.abs(
238
+ await this.client.solautoPosition.utilizationRateBpsDrift()
239
+ );
240
+ consoleLog("Liq utilization rate diff:", utilizationRateDiff);
241
+
242
+ if (utilizationRateDiff >= 10) {
243
+ consoleLog("Refreshing before rebalance");
244
+ return true;
245
+ }
246
+
247
+ consoleLog("Not refreshing before rebalance");
248
+ return false;
249
+ }
250
+
251
+ private async assembleTransaction(): Promise<TransactionItemInputs> {
252
+ const { swapQuote, lookupTableAddresses, setupInstructions, swapIx } =
253
+ await this.swapManager.getSwapTxData();
254
+
255
+ const flashLoanDetails = this.flRequirements
256
+ ? this.getFlashLoanDetails()
257
+ : undefined;
258
+
259
+ let tx = transactionBuilder();
260
+
261
+ if (await this.refreshBeforeRebalance()) {
262
+ tx = tx.add(this.client.refreshIx());
263
+ }
264
+
265
+ const rebalanceDetails: RebalanceDetails = {
266
+ values: this.values,
267
+ rebalanceType: this.rebalanceType,
268
+ flashLoan: flashLoanDetails,
269
+ swapQuote,
270
+ targetLiqUtilizationRateBps: this.targetLiqUtilizationRateBps,
271
+ };
272
+
273
+ const firstRebalance = this.client.rebalanceIx(
274
+ RebalanceStep.PreSwap,
275
+ rebalanceDetails
276
+ );
277
+ const lastRebalance = this.client.rebalanceIx(
278
+ RebalanceStep.PostSwap,
279
+ rebalanceDetails
280
+ );
281
+
282
+ if (!flashLoanDetails) {
283
+ tx = tx.add([setupInstructions, firstRebalance, swapIx, lastRebalance]);
284
+ } else {
285
+ consoleLog("Flash loan details:", flashLoanDetails);
286
+
287
+ const exactOut = swapQuote.swapMode === "ExactOut";
288
+ const addFirstRebalance = hasFirstRebalance(this.rebalanceType);
289
+ const addLastRebalance = hasLastRebalance(this.rebalanceType);
290
+
291
+ const flashBorrowDest = exactOut
292
+ ? getTokenAccount(
293
+ this.client.solautoPosition.publicKey,
294
+ new PublicKey(swapQuote.outputMint)
295
+ )
296
+ : getTokenAccount(
297
+ toWeb3JsPublicKey(this.client.signer.publicKey),
298
+ new PublicKey(swapQuote.inputMint)
299
+ );
300
+
301
+ tx = tx.add([
302
+ setupInstructions,
303
+ this.client.flProvider.flashBorrow(flashLoanDetails, flashBorrowDest),
304
+ ...(addFirstRebalance ? [firstRebalance] : []),
305
+ swapIx,
306
+ ...(addLastRebalance ? [lastRebalance] : []),
307
+ this.client.flProvider.flashRepay(flashLoanDetails),
308
+ ]);
309
+ }
310
+
311
+ return {
312
+ tx,
313
+ lookupTableAddresses,
314
+ };
315
+ }
316
+
317
+ public async buildRebalanceTx(
318
+ attemptNum: number
319
+ ): Promise<TransactionItemInputs | undefined> {
320
+ await this.client.solautoPosition.refreshPositionState();
321
+
322
+ if (!this.shouldProceedWithRebalance()) {
323
+ this.client.log("Not eligible for a rebalance");
324
+ return undefined;
325
+ }
326
+
327
+ await this.setRebalanceDetails(attemptNum);
328
+ return await this.assembleTransaction();
329
+ }
330
+ }