@haven-fi/solauto-sdk 1.0.582 → 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 (260) 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/generated/accounts/solautoPosition.js +2 -2
  5. package/dist/generated/errors/solauto.d.ts +14 -2
  6. package/dist/generated/errors/solauto.d.ts.map +1 -1
  7. package/dist/generated/errors/solauto.js +27 -5
  8. package/dist/generated/instructions/claimReferralFees.d.ts +1 -1
  9. package/dist/generated/instructions/claimReferralFees.d.ts.map +1 -1
  10. package/dist/generated/instructions/closePosition.d.ts +1 -1
  11. package/dist/generated/instructions/closePosition.d.ts.map +1 -1
  12. package/dist/generated/instructions/closePosition.js +2 -2
  13. package/dist/generated/instructions/marginfiOpenPosition.d.ts +1 -3
  14. package/dist/generated/instructions/marginfiOpenPosition.d.ts.map +1 -1
  15. package/dist/generated/instructions/marginfiOpenPosition.js +0 -1
  16. package/dist/generated/instructions/marginfiRebalance.d.ts +7 -3
  17. package/dist/generated/instructions/marginfiRebalance.d.ts.map +1 -1
  18. package/dist/generated/instructions/marginfiRebalance.js +3 -1
  19. package/dist/generated/types/index.d.ts +7 -1
  20. package/dist/generated/types/index.d.ts.map +1 -1
  21. package/dist/generated/types/index.js +7 -1
  22. package/dist/generated/types/positionData.d.ts +2 -2
  23. package/dist/generated/types/positionData.d.ts.map +1 -1
  24. package/dist/generated/types/positionData.js +1 -1
  25. package/dist/generated/types/positionState.d.ts +7 -7
  26. package/dist/generated/types/positionState.d.ts.map +1 -1
  27. package/dist/generated/types/positionState.js +3 -3
  28. package/dist/generated/types/{positionTokenUsage.d.ts → positionTokenState.d.ts} +6 -8
  29. package/dist/generated/types/positionTokenState.d.ts.map +1 -0
  30. package/dist/generated/types/{positionTokenUsage.js → positionTokenState.js} +6 -7
  31. package/dist/generated/types/rebalanceData.d.ts +7 -13
  32. package/dist/generated/types/rebalanceData.d.ts.map +1 -1
  33. package/dist/generated/types/rebalanceData.js +3 -6
  34. package/dist/generated/types/rebalanceDirection.d.ts +3 -2
  35. package/dist/generated/types/rebalanceDirection.d.ts.map +1 -1
  36. package/dist/generated/types/rebalanceDirection.js +3 -2
  37. package/dist/generated/types/rebalanceInstructionData.d.ts +27 -0
  38. package/dist/generated/types/rebalanceInstructionData.d.ts.map +1 -0
  39. package/dist/generated/types/rebalanceInstructionData.js +22 -0
  40. package/dist/generated/types/rebalanceStateValues.d.ts +27 -0
  41. package/dist/generated/types/rebalanceStateValues.d.ts.map +1 -0
  42. package/dist/generated/types/rebalanceStateValues.js +22 -0
  43. package/dist/generated/types/rebalanceStep.d.ts +15 -0
  44. package/dist/generated/types/rebalanceStep.d.ts.map +1 -0
  45. package/dist/generated/types/rebalanceStep.js +22 -0
  46. package/dist/generated/types/solautoRebalanceType.d.ts +4 -5
  47. package/dist/generated/types/solautoRebalanceType.d.ts.map +1 -1
  48. package/dist/generated/types/solautoRebalanceType.js +4 -5
  49. package/dist/generated/types/solautoSettingsParameters.d.ts +2 -15
  50. package/dist/generated/types/solautoSettingsParameters.d.ts.map +1 -1
  51. package/dist/generated/types/solautoSettingsParameters.js +1 -5
  52. package/dist/generated/types/solautoSettingsParametersInp.d.ts +1 -12
  53. package/dist/generated/types/solautoSettingsParametersInp.d.ts.map +1 -1
  54. package/dist/generated/types/solautoSettingsParametersInp.js +0 -3
  55. package/dist/generated/types/swapType.d.ts +15 -0
  56. package/dist/generated/types/swapType.d.ts.map +1 -0
  57. package/dist/generated/types/swapType.js +22 -0
  58. package/dist/generated/types/tokenBalanceChange.d.ts +21 -0
  59. package/dist/generated/types/tokenBalanceChange.d.ts.map +1 -0
  60. package/dist/generated/types/tokenBalanceChange.js +19 -0
  61. package/dist/generated/types/tokenBalanceChangeType.d.ts +18 -0
  62. package/dist/generated/types/tokenBalanceChangeType.d.ts.map +1 -0
  63. package/dist/generated/types/tokenBalanceChangeType.js +25 -0
  64. package/dist/generated/types/updatePositionData.d.ts +2 -2
  65. package/dist/generated/types/updatePositionData.d.ts.map +1 -1
  66. package/dist/generated/types/updatePositionData.js +1 -1
  67. package/dist/index.d.ts +8 -6
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +5 -5
  70. package/dist/marginfi-sdk/types/interestRateConfig.d.ts +3 -1
  71. package/dist/marginfi-sdk/types/interestRateConfig.d.ts.map +1 -1
  72. package/dist/marginfi-sdk/types/interestRateConfig.js +2 -1
  73. package/dist/services/flashLoans/flProviderAggregator.d.ts +19 -0
  74. package/dist/services/flashLoans/flProviderAggregator.d.ts.map +1 -0
  75. package/dist/services/flashLoans/flProviderAggregator.js +46 -0
  76. package/dist/services/flashLoans/flProviderBase.d.ts +23 -0
  77. package/dist/services/flashLoans/flProviderBase.d.ts.map +1 -0
  78. package/dist/services/flashLoans/flProviderBase.js +37 -0
  79. package/dist/services/flashLoans/index.d.ts +4 -0
  80. package/dist/services/flashLoans/index.d.ts.map +1 -0
  81. package/dist/services/flashLoans/index.js +19 -0
  82. package/dist/services/flashLoans/marginfiFlProvider.d.ts +25 -0
  83. package/dist/services/flashLoans/marginfiFlProvider.d.ts.map +1 -0
  84. package/dist/services/flashLoans/marginfiFlProvider.js +246 -0
  85. package/dist/services/index.d.ts +6 -0
  86. package/dist/services/index.d.ts.map +1 -0
  87. package/dist/services/index.js +21 -0
  88. package/dist/services/rebalance/index.d.ts +3 -0
  89. package/dist/services/rebalance/index.d.ts.map +1 -0
  90. package/dist/services/rebalance/index.js +18 -0
  91. package/dist/services/rebalance/rebalanceSwapManager.d.ts +30 -0
  92. package/dist/services/rebalance/rebalanceSwapManager.d.ts.map +1 -0
  93. package/dist/services/rebalance/rebalanceSwapManager.js +144 -0
  94. package/dist/services/rebalance/rebalanceTxBuilder.d.ts +22 -0
  95. package/dist/services/rebalance/rebalanceTxBuilder.d.ts.map +1 -0
  96. package/dist/services/rebalance/rebalanceTxBuilder.js +200 -0
  97. package/dist/services/rebalance/rebalanceValues.d.ts +31 -0
  98. package/dist/services/rebalance/rebalanceValues.d.ts.map +1 -0
  99. package/dist/services/rebalance/rebalanceValues.js +118 -0
  100. package/dist/services/rebalance/solautoFees.d.ts +13 -0
  101. package/dist/services/rebalance/solautoFees.d.ts.map +1 -0
  102. package/dist/services/rebalance/solautoFees.js +54 -0
  103. package/dist/services/solauto/index.d.ts +5 -0
  104. package/dist/services/solauto/index.d.ts.map +1 -0
  105. package/dist/{clients → services/solauto}/referralStateManager.d.ts +4 -5
  106. package/dist/services/solauto/referralStateManager.d.ts.map +1 -0
  107. package/dist/{clients → services/solauto}/referralStateManager.js +10 -12
  108. package/dist/services/solauto/solautoClient.d.ts +59 -0
  109. package/dist/services/solauto/solautoClient.d.ts.map +1 -0
  110. package/dist/{clients → services/solauto}/solautoClient.js +78 -109
  111. package/dist/services/solauto/solautoMarginfiClient.d.ts +34 -0
  112. package/dist/services/solauto/solautoMarginfiClient.d.ts.map +1 -0
  113. package/dist/services/solauto/solautoMarginfiClient.js +322 -0
  114. package/dist/{clients → services/solauto}/txHandler.d.ts +11 -2
  115. package/dist/services/solauto/txHandler.d.ts.map +1 -0
  116. package/dist/services/solauto/txHandler.js +38 -0
  117. package/dist/services/swap/index.d.ts +2 -0
  118. package/dist/services/swap/index.d.ts.map +1 -0
  119. package/dist/{utils/solauto → services/swap}/index.js +1 -2
  120. package/dist/services/swap/jupSwapManager.d.ts +37 -0
  121. package/dist/services/swap/jupSwapManager.d.ts.map +1 -0
  122. package/dist/services/swap/jupSwapManager.js +108 -0
  123. package/dist/services/transactions/index.d.ts.map +1 -0
  124. package/dist/{transactions → services/transactions}/transactionUtils.d.ts +3 -5
  125. package/dist/services/transactions/transactionUtils.d.ts.map +1 -0
  126. package/dist/{transactions → services/transactions}/transactionUtils.js +29 -137
  127. package/dist/{transactions → services/transactions}/transactionsManager.d.ts +4 -4
  128. package/dist/services/transactions/transactionsManager.d.ts.map +1 -0
  129. package/dist/{transactions → services/transactions}/transactionsManager.js +10 -8
  130. package/dist/solautoPosition/index.d.ts +4 -0
  131. package/dist/solautoPosition/index.d.ts.map +1 -0
  132. package/dist/solautoPosition/index.js +19 -0
  133. package/dist/solautoPosition/marginfiSolautoPositionEx.d.ts +14 -0
  134. package/dist/solautoPosition/marginfiSolautoPositionEx.d.ts.map +1 -0
  135. package/dist/solautoPosition/marginfiSolautoPositionEx.js +73 -0
  136. package/dist/solautoPosition/solautoPositionEx.d.ts +67 -0
  137. package/dist/solautoPosition/solautoPositionEx.d.ts.map +1 -0
  138. package/dist/solautoPosition/solautoPositionEx.js +143 -0
  139. package/dist/solautoPosition/utils.d.ts +17 -0
  140. package/dist/solautoPosition/utils.d.ts.map +1 -0
  141. package/dist/solautoPosition/utils.js +115 -0
  142. package/dist/types/solauto.d.ts +19 -1
  143. package/dist/types/solauto.d.ts.map +1 -1
  144. package/dist/utils/generalUtils.d.ts +1 -0
  145. package/dist/utils/generalUtils.d.ts.map +1 -1
  146. package/dist/utils/generalUtils.js +9 -1
  147. package/dist/utils/index.d.ts +1 -1
  148. package/dist/utils/index.d.ts.map +1 -1
  149. package/dist/utils/index.js +1 -1
  150. package/dist/utils/jitoUtils.d.ts.map +1 -1
  151. package/dist/utils/jupiterUtils.d.ts +3 -28
  152. package/dist/utils/jupiterUtils.d.ts.map +1 -1
  153. package/dist/utils/jupiterUtils.js +2 -73
  154. package/dist/utils/marginfiUtils.d.ts +4 -3
  155. package/dist/utils/marginfiUtils.d.ts.map +1 -1
  156. package/dist/utils/marginfiUtils.js +47 -18
  157. package/dist/utils/numberUtils.d.ts +3 -6
  158. package/dist/utils/numberUtils.d.ts.map +1 -1
  159. package/dist/utils/numberUtils.js +13 -48
  160. package/dist/utils/solanaUtils.js +2 -2
  161. package/dist/utils/{solauto/generalUtils.d.ts → solautoUtils.d.ts} +9 -16
  162. package/dist/utils/solautoUtils.d.ts.map +1 -0
  163. package/dist/utils/{solauto/generalUtils.js → solautoUtils.js} +48 -173
  164. package/local/createTokenAccounts.ts +1 -5
  165. package/local/logPositions.ts +22 -68
  166. package/local/shared.ts +29 -24
  167. package/local/txSandbox.ts +27 -0
  168. package/local/updateMarginfiLUT.ts +80 -4
  169. package/package.json +3 -6
  170. package/src/constants/solautoConstants.ts +4 -9
  171. package/src/generated/accounts/solautoPosition.ts +2 -2
  172. package/src/generated/errors/solauto.ts +45 -4
  173. package/src/generated/instructions/claimReferralFees.ts +1 -1
  174. package/src/generated/instructions/closePosition.ts +3 -3
  175. package/src/generated/instructions/marginfiOpenPosition.ts +0 -7
  176. package/src/generated/instructions/marginfiRebalance.ts +12 -3
  177. package/src/generated/types/index.ts +7 -1
  178. package/src/generated/types/positionData.ts +3 -3
  179. package/src/generated/types/positionState.ts +12 -12
  180. package/src/generated/types/{positionTokenUsage.ts → positionTokenState.ts} +13 -16
  181. package/src/generated/types/rebalanceData.ts +16 -27
  182. package/src/generated/types/rebalanceDirection.ts +1 -0
  183. package/src/generated/types/rebalanceInstructionData.ts +62 -0
  184. package/src/generated/types/rebalanceStateValues.ts +59 -0
  185. package/src/generated/types/rebalanceStep.ts +25 -0
  186. package/src/generated/types/solautoRebalanceType.ts +0 -1
  187. package/src/generated/types/solautoSettingsParameters.ts +4 -25
  188. package/src/generated/types/solautoSettingsParametersInp.ts +2 -24
  189. package/src/generated/types/swapType.ts +22 -0
  190. package/src/generated/types/tokenBalanceChange.ts +46 -0
  191. package/src/generated/types/tokenBalanceChangeType.ts +28 -0
  192. package/src/generated/types/updatePositionData.ts +3 -3
  193. package/src/index.ts +8 -8
  194. package/src/marginfi-sdk/types/interestRateConfig.ts +6 -2
  195. package/src/services/flashLoans/flProviderAggregator.ts +74 -0
  196. package/src/services/flashLoans/flProviderBase.ts +88 -0
  197. package/src/services/flashLoans/index.ts +3 -0
  198. package/src/services/flashLoans/marginfiFlProvider.ts +392 -0
  199. package/src/services/index.ts +5 -0
  200. package/src/services/rebalance/index.ts +2 -0
  201. package/src/services/rebalance/rebalanceSwapManager.ts +218 -0
  202. package/src/services/rebalance/rebalanceTxBuilder.ts +330 -0
  203. package/src/services/rebalance/rebalanceValues.ts +232 -0
  204. package/src/services/rebalance/solautoFees.ts +61 -0
  205. package/src/services/solauto/index.ts +4 -0
  206. package/src/{clients → services/solauto}/referralStateManager.ts +17 -31
  207. package/src/{clients → services/solauto}/solautoClient.ts +142 -205
  208. package/src/services/solauto/solautoMarginfiClient.ts +472 -0
  209. package/src/services/solauto/txHandler.ts +69 -0
  210. package/src/services/swap/index.ts +1 -0
  211. package/src/services/swap/jupSwapManager.ts +189 -0
  212. package/src/{transactions → services/transactions}/transactionUtils.ts +40 -280
  213. package/src/{transactions → services/transactions}/transactionsManager.ts +15 -10
  214. package/src/solautoPosition/index.ts +3 -0
  215. package/src/solautoPosition/marginfiSolautoPositionEx.ts +111 -0
  216. package/src/solautoPosition/solautoPositionEx.ts +281 -0
  217. package/src/solautoPosition/utils.ts +188 -0
  218. package/src/types/solauto.ts +30 -2
  219. package/src/utils/generalUtils.ts +9 -1
  220. package/src/utils/index.ts +2 -2
  221. package/src/utils/jitoUtils.ts +0 -4
  222. package/src/utils/jupiterUtils.ts +3 -164
  223. package/src/utils/marginfiUtils.ts +77 -43
  224. package/src/utils/numberUtils.ts +18 -77
  225. package/src/utils/solanaUtils.ts +1 -1
  226. package/src/utils/{solauto/generalUtils.ts → solautoUtils.ts} +66 -288
  227. package/tests/transactions/shared.ts +135 -0
  228. package/tests/transactions/solautoMarginfi.ts +8 -198
  229. package/tests/unit/accounts.ts +3 -10
  230. package/tests/unit/lookupTables.ts +23 -2
  231. package/tests/unit/rebalanceCalculations.ts +65 -343
  232. package/dist/clients/index.d.ts +0 -5
  233. package/dist/clients/index.d.ts.map +0 -1
  234. package/dist/clients/referralStateManager.d.ts.map +0 -1
  235. package/dist/clients/solautoClient.d.ts +0 -71
  236. package/dist/clients/solautoClient.d.ts.map +0 -1
  237. package/dist/clients/solautoMarginfiClient.d.ts +0 -51
  238. package/dist/clients/solautoMarginfiClient.d.ts.map +0 -1
  239. package/dist/clients/solautoMarginfiClient.js +0 -497
  240. package/dist/clients/txHandler.d.ts.map +0 -1
  241. package/dist/clients/txHandler.js +0 -23
  242. package/dist/generated/types/positionTokenUsage.d.ts.map +0 -1
  243. package/dist/transactions/index.d.ts.map +0 -1
  244. package/dist/transactions/transactionUtils.d.ts.map +0 -1
  245. package/dist/transactions/transactionsManager.d.ts.map +0 -1
  246. package/dist/utils/solauto/generalUtils.d.ts.map +0 -1
  247. package/dist/utils/solauto/index.d.ts +0 -3
  248. package/dist/utils/solauto/index.d.ts.map +0 -1
  249. package/dist/utils/solauto/rebalanceUtils.d.ts +0 -30
  250. package/dist/utils/solauto/rebalanceUtils.d.ts.map +0 -1
  251. package/dist/utils/solauto/rebalanceUtils.js +0 -287
  252. package/src/clients/index.ts +0 -4
  253. package/src/clients/solautoMarginfiClient.ts +0 -774
  254. package/src/clients/txHandler.ts +0 -38
  255. package/src/utils/solauto/index.ts +0 -2
  256. package/src/utils/solauto/rebalanceUtils.ts +0 -562
  257. package/dist/{clients → services/solauto}/index.js +2 -2
  258. /package/dist/{transactions → services/transactions}/index.d.ts +0 -0
  259. /package/dist/{transactions → services/transactions}/index.js +0 -0
  260. /package/src/{transactions → services/transactions}/index.ts +0 -0
@@ -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
+ }
@@ -0,0 +1,232 @@
1
+ import {
2
+ RebalanceDirection,
3
+ TokenBalanceChange,
4
+ TokenBalanceChangeType,
5
+ } from "../../generated";
6
+ import { SolautoPositionEx } from "../../solautoPosition";
7
+ import {
8
+ fromBps,
9
+ getLiqUtilzationRateBps,
10
+ maxRepayToBps,
11
+ toBps,
12
+ } from "../../utils";
13
+ import { SolautoFeesBps } from "./solautoFees";
14
+
15
+ export interface PositionValues {
16
+ supplyUsd: number;
17
+ debtUsd: number;
18
+ }
19
+
20
+ export interface DebtAdjustment {
21
+ debtAdjustmentUsd: number;
22
+ endResult: PositionValues;
23
+ intermediaryLiqUtilizationRateBps: number;
24
+ }
25
+
26
+ export interface RebalanceFeesBps {
27
+ solauto: number;
28
+ lpBorrow: number;
29
+ flashLoan: number;
30
+ }
31
+
32
+ interface ApplyDebtAdjustmentResult {
33
+ newPos: PositionValues;
34
+ intermediaryLiqUtilizationRateBps: number;
35
+ }
36
+
37
+ export function applyDebtAdjustmentUsd(
38
+ debtAdjustmentUsd: number,
39
+ pos: PositionValues,
40
+ fees: RebalanceFeesBps,
41
+ liqThreshold: number
42
+ ): ApplyDebtAdjustmentResult {
43
+ const newPos = { ...pos };
44
+ const isBoost = debtAdjustmentUsd > 0;
45
+
46
+ const daMinusSolautoFees =
47
+ debtAdjustmentUsd - debtAdjustmentUsd * fromBps(fees.solauto);
48
+ const daWithFlashLoan = debtAdjustmentUsd * (1.0 + fromBps(fees.flashLoan));
49
+
50
+ let intermediaryLiqUtilizationRateBps = 0;
51
+ if (isBoost) {
52
+ newPos.debtUsd +=
53
+ daWithFlashLoan * fromBps(fees.lpBorrow) + daWithFlashLoan;
54
+ intermediaryLiqUtilizationRateBps = getLiqUtilzationRateBps(
55
+ newPos.supplyUsd,
56
+ newPos.debtUsd,
57
+ toBps(liqThreshold)
58
+ );
59
+ newPos.supplyUsd += daMinusSolautoFees;
60
+ } else {
61
+ newPos.supplyUsd += daWithFlashLoan;
62
+ intermediaryLiqUtilizationRateBps = getLiqUtilzationRateBps(
63
+ newPos.supplyUsd,
64
+ newPos.debtUsd,
65
+ toBps(liqThreshold)
66
+ );
67
+ newPos.debtUsd += daMinusSolautoFees;
68
+ }
69
+
70
+ return { newPos, intermediaryLiqUtilizationRateBps };
71
+ }
72
+
73
+ export function getDebtAdjustment(
74
+ liqThreshold: number,
75
+ pos: PositionValues,
76
+ fees: RebalanceFeesBps,
77
+ targetLiqUtilizationRateBps: number
78
+ ): DebtAdjustment {
79
+ const isBoost =
80
+ getLiqUtilzationRateBps(pos.supplyUsd, pos.debtUsd, toBps(liqThreshold)) <
81
+ targetLiqUtilizationRateBps;
82
+
83
+ const targetUtilizationRate = fromBps(targetLiqUtilizationRateBps);
84
+ const actualizedFee = 1.0 - fromBps(fees.solauto);
85
+ const flFee = fromBps(fees.flashLoan);
86
+ const lpBorrowFee = fromBps(fees.lpBorrow);
87
+
88
+ const debtAdjustmentUsd = isBoost
89
+ ? (targetUtilizationRate * liqThreshold * pos.supplyUsd - pos.debtUsd) /
90
+ (1.0 +
91
+ lpBorrowFee +
92
+ flFee -
93
+ targetUtilizationRate * actualizedFee * liqThreshold)
94
+ : (targetUtilizationRate * liqThreshold * pos.supplyUsd - pos.debtUsd) /
95
+ (actualizedFee - targetUtilizationRate * liqThreshold * (1.0 + flFee));
96
+
97
+ const newPos = applyDebtAdjustmentUsd(
98
+ debtAdjustmentUsd,
99
+ pos,
100
+ fees,
101
+ liqThreshold
102
+ );
103
+
104
+ return {
105
+ debtAdjustmentUsd,
106
+ endResult: newPos.newPos,
107
+ intermediaryLiqUtilizationRateBps: newPos.intermediaryLiqUtilizationRateBps,
108
+ };
109
+ }
110
+
111
+ function getTokenBalanceChange(): TokenBalanceChange | undefined {
112
+ // TODO: DCA, limit orders, take profit, stop loss, etc.
113
+ return undefined;
114
+ }
115
+
116
+ function getTargetLiqUtilizationRateBps(
117
+ solautoPosition: SolautoPositionEx,
118
+ targetLiqUtilizationRateBps: number | undefined,
119
+ tokenBalanceChange: TokenBalanceChange | undefined
120
+ ): number {
121
+ if (targetLiqUtilizationRateBps !== undefined) {
122
+ return targetLiqUtilizationRateBps;
123
+ }
124
+
125
+ const currentRate = solautoPosition.state().liqUtilizationRateBps;
126
+
127
+ if (currentRate <= solautoPosition.boostFromBps()) {
128
+ return solautoPosition.settings()!.boostToBps;
129
+ } else if (currentRate >= solautoPosition.repayFromBps()) {
130
+ return solautoPosition.settings()!.repayToBps;
131
+ }
132
+ // TODO: DCA, limit orders, take profit, stop loss, etc.
133
+ // else if (tokenBalanceChange !== null) {
134
+ // return currentRate;
135
+ // }
136
+
137
+ throw new Error("Invalid rebalance condition");
138
+ }
139
+
140
+ function getAdjustedPositionValues(
141
+ solautoPosition: SolautoPositionEx,
142
+ tokenBalanceChange: TokenBalanceChange | undefined
143
+ ): PositionValues {
144
+ let supplyUsd = solautoPosition.supplyUsd();
145
+ const debtUsd = solautoPosition.debtUsd();
146
+
147
+ if (tokenBalanceChange) {
148
+ const tb = tokenBalanceChange;
149
+ switch (tb.changeType) {
150
+ case TokenBalanceChangeType.PreSwapDeposit:
151
+ case TokenBalanceChangeType.PostSwapDeposit:
152
+ supplyUsd += Number(tb.amountUsd);
153
+ break;
154
+ case TokenBalanceChangeType.PostRebalanceWithdrawDebtToken:
155
+ case TokenBalanceChangeType.PostRebalanceWithdrawSupplyToken:
156
+ supplyUsd -= Number(tb.amountUsd);
157
+ break;
158
+ default:
159
+ break;
160
+ }
161
+ }
162
+
163
+ return {
164
+ supplyUsd,
165
+ debtUsd,
166
+ };
167
+ }
168
+
169
+ function getRebalanceDirection(
170
+ solautoPosition: SolautoPositionEx,
171
+ targetLtvBps: number
172
+ ): RebalanceDirection {
173
+ return solautoPosition.state().liqUtilizationRateBps < targetLtvBps
174
+ ? RebalanceDirection.Boost
175
+ : RebalanceDirection.Repay;
176
+ }
177
+
178
+ export interface RebalanceValues extends DebtAdjustment {
179
+ rebalanceDirection: RebalanceDirection;
180
+ tokenBalanceChange?: TokenBalanceChange;
181
+ repayingCloseToMaxLtv: boolean;
182
+ }
183
+
184
+ export function getRebalanceValues(
185
+ solautoPosition: SolautoPositionEx,
186
+ solautoFeeBps: SolautoFeesBps,
187
+ flFeeBps: number,
188
+ targetLiqUtilizationRateBps?: number
189
+ ): RebalanceValues {
190
+ const tokenBalanceChange = getTokenBalanceChange();
191
+
192
+ const targetRate = getTargetLiqUtilizationRateBps(
193
+ solautoPosition,
194
+ targetLiqUtilizationRateBps,
195
+ tokenBalanceChange
196
+ );
197
+
198
+ const rebalanceDirection = getRebalanceDirection(solautoPosition, targetRate);
199
+
200
+ const position = getAdjustedPositionValues(
201
+ solautoPosition,
202
+ tokenBalanceChange
203
+ );
204
+
205
+ const fees: RebalanceFeesBps = {
206
+ solauto: solautoFeeBps.getSolautoFeesBps(rebalanceDirection).total,
207
+ lpBorrow: solautoPosition.state().debt.borrowFeeBps,
208
+ flashLoan: flFeeBps,
209
+ };
210
+
211
+ const debtAdjustment = getDebtAdjustment(
212
+ fromBps(solautoPosition.state().liqThresholdBps),
213
+ position,
214
+ fees,
215
+ targetRate
216
+ );
217
+
218
+ const repayingCloseToMaxLtv =
219
+ rebalanceDirection === RebalanceDirection.Repay &&
220
+ targetRate >=
221
+ maxRepayToBps(
222
+ solautoPosition.state().maxLtvBps,
223
+ solautoPosition.state().liqThresholdBps
224
+ );
225
+
226
+ return {
227
+ ...debtAdjustment,
228
+ rebalanceDirection,
229
+ tokenBalanceChange,
230
+ repayingCloseToMaxLtv,
231
+ };
232
+ }
@@ -0,0 +1,61 @@
1
+ import { REFERRER_PERCENTAGE } from "../../constants";
2
+ import { RebalanceDirection } from "../../generated";
3
+
4
+ export class SolautoFeesBps {
5
+ constructor(
6
+ private isReferred: boolean,
7
+ private targetLiqUtilizationRateBps: number | undefined,
8
+ private positionNetWorthUsd: number
9
+ ) {}
10
+
11
+ public getSolautoFeesBps(rebalanceDirection: RebalanceDirection) {
12
+ const minSize = 10_000; // Minimum position size
13
+ const maxSize = 250_000; // Maximum position size
14
+ const maxFeeBps = 50; // Fee in basis points for minSize (0.5%)
15
+ const minFeeBps = 25; // Fee in basis points for maxSize (0.25%)
16
+ const k = 1.5;
17
+
18
+ if (
19
+ this.targetLiqUtilizationRateBps !== undefined &&
20
+ this.targetLiqUtilizationRateBps === 0
21
+ ) {
22
+ return {
23
+ solauto: 0,
24
+ referrer: 0,
25
+ total: 0,
26
+ };
27
+ }
28
+
29
+ let feeBps: number = 0;
30
+
31
+ if (
32
+ this.targetLiqUtilizationRateBps !== undefined ||
33
+ rebalanceDirection === RebalanceDirection.Repay
34
+ ) {
35
+ feeBps = 25;
36
+ } else if (this.positionNetWorthUsd <= minSize) {
37
+ feeBps = maxFeeBps;
38
+ } else if (this.positionNetWorthUsd >= maxSize) {
39
+ feeBps = minFeeBps;
40
+ } else {
41
+ const t =
42
+ (Math.log(this.positionNetWorthUsd) - Math.log(minSize)) /
43
+ (Math.log(maxSize) - Math.log(minSize));
44
+ feeBps = Math.round(
45
+ minFeeBps + (maxFeeBps - minFeeBps) * (1 - Math.pow(t, k))
46
+ );
47
+ }
48
+
49
+ let referrer = 0;
50
+ if (this.isReferred) {
51
+ feeBps *= 1.0 - REFERRER_PERCENTAGE;
52
+ referrer = Math.floor(feeBps * REFERRER_PERCENTAGE);
53
+ }
54
+
55
+ return {
56
+ solauto: feeBps - referrer,
57
+ referrer,
58
+ total: feeBps,
59
+ };
60
+ }
61
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./referralStateManager";
2
+ export * from "./solautoClient";
3
+ export * from "./solautoMarginfiClient";
4
+ export * from "./txHandler";
@@ -1,30 +1,18 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
2
  import { NATIVE_MINT } from "@solana/spl-token";
3
- import {
4
- publicKey,
5
- Signer,
6
- signerIdentity,
7
- TransactionBuilder,
8
- Umi,
9
- } from "@metaplex-foundation/umi";
3
+ import { publicKey, TransactionBuilder, Umi } from "@metaplex-foundation/umi";
10
4
  import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
11
- import {
12
- WalletAdapter,
13
- walletAdapterIdentity,
14
- } from "@metaplex-foundation/umi-signer-wallet-adapters";
15
5
  import {
16
6
  claimReferralFees,
17
7
  ReferralState,
18
8
  safeFetchReferralState,
19
9
  updateReferralStates,
20
- } from "../generated";
21
- import { getReferralState, getTokenAccount } from "../utils";
10
+ } from "../../generated";
11
+ import { getReferralState, getTokenAccount } from "../../utils";
22
12
  import { TxHandler } from "./txHandler";
23
- import { SOLAUTO_LUT } from "../constants";
13
+ import { SOLAUTO_LUT } from "../../constants";
24
14
 
25
15
  export interface ReferralStateManagerArgs {
26
- signer?: Signer;
27
- wallet?: WalletAdapter;
28
16
  authority?: PublicKey;
29
17
  referralState?: PublicKey;
30
18
  referredByAuthority?: PublicKey;
@@ -41,16 +29,6 @@ export class ReferralStateManager extends TxHandler {
41
29
  public referredByState?: PublicKey;
42
30
 
43
31
  async initialize(args: ReferralStateManagerArgs) {
44
- if (!args.signer && !args.wallet) {
45
- throw new Error("Signer or wallet must be provided");
46
- }
47
- this.umi = this.umi.use(
48
- args.signer
49
- ? signerIdentity(args.signer, true)
50
- : walletAdapterIdentity(args.wallet!, true)
51
- );
52
- this.signer = this.umi.identity;
53
-
54
32
  this.referralState =
55
33
  args.referralState ??
56
34
  getReferralState(
@@ -58,11 +36,7 @@ export class ReferralStateManager extends TxHandler {
58
36
  this.programId
59
37
  );
60
38
 
61
- this.referralStateData = await safeFetchReferralState(
62
- this.umi,
63
- publicKey(this.referralState),
64
- { commitment: "confirmed" }
65
- );
39
+ await this.refetchReferralState();
66
40
  this.authority = this.referralStateData?.authority
67
41
  ? toWeb3JsPublicKey(this.referralStateData.authority)
68
42
  : (args.authority ?? toWeb3JsPublicKey(this.signer.publicKey));
@@ -83,6 +57,14 @@ export class ReferralStateManager extends TxHandler {
83
57
  : [SOLAUTO_LUT];
84
58
  }
85
59
 
60
+ async refetchReferralState() {
61
+ this.referralStateData = await safeFetchReferralState(
62
+ this.umi,
63
+ publicKey(this.referralState),
64
+ { commitment: "confirmed" }
65
+ );
66
+ }
67
+
86
68
  setReferredBy(referredBy?: PublicKey) {
87
69
  const hasReferredBy =
88
70
  this.referralStateData &&
@@ -105,6 +87,10 @@ export class ReferralStateManager extends TxHandler {
105
87
  : undefined;
106
88
  }
107
89
 
90
+ isReferred(): boolean {
91
+ return Boolean(this.referredByState);
92
+ }
93
+
108
94
  updateReferralStatesIx(
109
95
  destFeesMint?: PublicKey,
110
96
  lookupTable?: PublicKey