@kamino-finance/klend-sdk 3.2.26 → 4.0.0

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 (725) hide show
  1. package/dist/classes/action.d.ts +1 -0
  2. package/dist/classes/action.d.ts.map +1 -0
  3. package/dist/classes/action.js +1130 -1186
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/curve.d.ts +1 -0
  6. package/dist/classes/curve.d.ts.map +1 -0
  7. package/dist/classes/curve.js +1 -1
  8. package/dist/classes/curve.js.map +1 -1
  9. package/dist/classes/fraction.d.ts +1 -0
  10. package/dist/classes/fraction.d.ts.map +1 -0
  11. package/dist/classes/fraction.js +7 -6
  12. package/dist/classes/fraction.js.map +1 -1
  13. package/dist/classes/index.d.ts +1 -0
  14. package/dist/classes/index.d.ts.map +1 -0
  15. package/dist/classes/index.js.map +1 -1
  16. package/dist/classes/jupiterPerps.d.ts +1 -0
  17. package/dist/classes/jupiterPerps.d.ts.map +1 -0
  18. package/dist/classes/jupiterPerps.js +7 -18
  19. package/dist/classes/jupiterPerps.js.map +1 -1
  20. package/dist/classes/manager.d.ts +1 -0
  21. package/dist/classes/manager.d.ts.map +1 -0
  22. package/dist/classes/manager.js +131 -158
  23. package/dist/classes/manager.js.map +1 -1
  24. package/dist/classes/market.d.ts +1 -0
  25. package/dist/classes/market.d.ts.map +1 -0
  26. package/dist/classes/market.js +620 -714
  27. package/dist/classes/market.js.map +1 -1
  28. package/dist/classes/obligation.d.ts +1 -0
  29. package/dist/classes/obligation.d.ts.map +1 -0
  30. package/dist/classes/obligation.js +60 -62
  31. package/dist/classes/obligation.js.map +1 -1
  32. package/dist/classes/reserve.d.ts +1 -0
  33. package/dist/classes/reserve.d.ts.map +1 -0
  34. package/dist/classes/reserve.js +120 -129
  35. package/dist/classes/reserve.js.map +1 -1
  36. package/dist/classes/shared.d.ts +1 -0
  37. package/dist/classes/shared.d.ts.map +1 -0
  38. package/dist/classes/shared.js.map +1 -1
  39. package/dist/classes/utils.d.ts +1 -0
  40. package/dist/classes/utils.d.ts.map +1 -0
  41. package/dist/classes/utils.js +3 -3
  42. package/dist/classes/utils.js.map +1 -1
  43. package/dist/classes/vault.d.ts +1 -0
  44. package/dist/classes/vault.d.ts.map +1 -0
  45. package/dist/classes/vault.js +334 -354
  46. package/dist/classes/vault.js.map +1 -1
  47. package/dist/client_kamino_manager.d.ts +1 -0
  48. package/dist/client_kamino_manager.d.ts.map +1 -0
  49. package/dist/client_kamino_manager.js +323 -326
  50. package/dist/client_kamino_manager.js.map +1 -1
  51. package/dist/idl_codegen/accounts/LendingMarket.d.ts +1 -0
  52. package/dist/idl_codegen/accounts/LendingMarket.d.ts.map +1 -0
  53. package/dist/idl_codegen/accounts/LendingMarket.js +89 -55
  54. package/dist/idl_codegen/accounts/LendingMarket.js.map +1 -1
  55. package/dist/idl_codegen/accounts/Obligation.d.ts +1 -0
  56. package/dist/idl_codegen/accounts/Obligation.d.ts.map +1 -0
  57. package/dist/idl_codegen/accounts/Obligation.js +87 -56
  58. package/dist/idl_codegen/accounts/Obligation.js.map +1 -1
  59. package/dist/idl_codegen/accounts/ReferrerState.d.ts +1 -0
  60. package/dist/idl_codegen/accounts/ReferrerState.d.ts.map +1 -0
  61. package/dist/idl_codegen/accounts/ReferrerState.js +22 -33
  62. package/dist/idl_codegen/accounts/ReferrerState.js.map +1 -1
  63. package/dist/idl_codegen/accounts/ReferrerTokenState.d.ts +1 -0
  64. package/dist/idl_codegen/accounts/ReferrerTokenState.d.ts.map +1 -0
  65. package/dist/idl_codegen/accounts/ReferrerTokenState.js +35 -37
  66. package/dist/idl_codegen/accounts/ReferrerTokenState.js.map +1 -1
  67. package/dist/idl_codegen/accounts/Reserve.d.ts +1 -0
  68. package/dist/idl_codegen/accounts/Reserve.d.ts.map +1 -0
  69. package/dist/idl_codegen/accounts/Reserve.js +60 -49
  70. package/dist/idl_codegen/accounts/Reserve.js.map +1 -1
  71. package/dist/idl_codegen/accounts/ShortUrl.d.ts +1 -0
  72. package/dist/idl_codegen/accounts/ShortUrl.d.ts.map +1 -0
  73. package/dist/idl_codegen/accounts/ShortUrl.js +22 -33
  74. package/dist/idl_codegen/accounts/ShortUrl.js.map +1 -1
  75. package/dist/idl_codegen/accounts/UserMetadata.d.ts +1 -0
  76. package/dist/idl_codegen/accounts/UserMetadata.d.ts.map +1 -0
  77. package/dist/idl_codegen/accounts/UserMetadata.js +34 -37
  78. package/dist/idl_codegen/accounts/UserMetadata.js.map +1 -1
  79. package/dist/idl_codegen/accounts/UserState.d.ts +1 -0
  80. package/dist/idl_codegen/accounts/UserState.d.ts.map +1 -0
  81. package/dist/idl_codegen/accounts/UserState.js +77 -48
  82. package/dist/idl_codegen/accounts/UserState.js.map +1 -1
  83. package/dist/idl_codegen/accounts/index.d.ts +1 -0
  84. package/dist/idl_codegen/accounts/index.d.ts.map +1 -0
  85. package/dist/idl_codegen/accounts/index.js.map +1 -1
  86. package/dist/idl_codegen/errors/anchor.d.ts +1 -0
  87. package/dist/idl_codegen/errors/anchor.d.ts.map +1 -0
  88. package/dist/idl_codegen/errors/anchor.js +270 -216
  89. package/dist/idl_codegen/errors/anchor.js.map +1 -1
  90. package/dist/idl_codegen/errors/custom.d.ts +1 -0
  91. package/dist/idl_codegen/errors/custom.d.ts.map +1 -0
  92. package/dist/idl_codegen/errors/custom.js +560 -448
  93. package/dist/idl_codegen/errors/custom.js.map +1 -1
  94. package/dist/idl_codegen/errors/index.d.ts +1 -0
  95. package/dist/idl_codegen/errors/index.d.ts.map +1 -0
  96. package/dist/idl_codegen/errors/index.js.map +1 -1
  97. package/dist/idl_codegen/instructions/borrowObligationLiquidity.d.ts +1 -0
  98. package/dist/idl_codegen/instructions/borrowObligationLiquidity.d.ts.map +1 -0
  99. package/dist/idl_codegen/instructions/borrowObligationLiquidity.js.map +1 -1
  100. package/dist/idl_codegen/instructions/deleteReferrerStateAndShortUrl.d.ts +1 -0
  101. package/dist/idl_codegen/instructions/deleteReferrerStateAndShortUrl.d.ts.map +1 -0
  102. package/dist/idl_codegen/instructions/deleteReferrerStateAndShortUrl.js.map +1 -1
  103. package/dist/idl_codegen/instructions/depositObligationCollateral.d.ts +1 -0
  104. package/dist/idl_codegen/instructions/depositObligationCollateral.d.ts.map +1 -0
  105. package/dist/idl_codegen/instructions/depositObligationCollateral.js.map +1 -1
  106. package/dist/idl_codegen/instructions/depositReserveLiquidity.d.ts +1 -0
  107. package/dist/idl_codegen/instructions/depositReserveLiquidity.d.ts.map +1 -0
  108. package/dist/idl_codegen/instructions/depositReserveLiquidity.js.map +1 -1
  109. package/dist/idl_codegen/instructions/depositReserveLiquidityAndObligationCollateral.d.ts +1 -0
  110. package/dist/idl_codegen/instructions/depositReserveLiquidityAndObligationCollateral.d.ts.map +1 -0
  111. package/dist/idl_codegen/instructions/depositReserveLiquidityAndObligationCollateral.js.map +1 -1
  112. package/dist/idl_codegen/instructions/flashBorrowReserveLiquidity.d.ts +1 -0
  113. package/dist/idl_codegen/instructions/flashBorrowReserveLiquidity.d.ts.map +1 -0
  114. package/dist/idl_codegen/instructions/flashBorrowReserveLiquidity.js.map +1 -1
  115. package/dist/idl_codegen/instructions/flashRepayReserveLiquidity.d.ts +1 -0
  116. package/dist/idl_codegen/instructions/flashRepayReserveLiquidity.d.ts.map +1 -0
  117. package/dist/idl_codegen/instructions/flashRepayReserveLiquidity.js.map +1 -1
  118. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts +1 -0
  119. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts.map +1 -0
  120. package/dist/idl_codegen/instructions/idlMissingTypes.js.map +1 -1
  121. package/dist/idl_codegen/instructions/index.d.ts +1 -0
  122. package/dist/idl_codegen/instructions/index.d.ts.map +1 -0
  123. package/dist/idl_codegen/instructions/index.js.map +1 -1
  124. package/dist/idl_codegen/instructions/initFarmsForReserve.d.ts +1 -0
  125. package/dist/idl_codegen/instructions/initFarmsForReserve.d.ts.map +1 -0
  126. package/dist/idl_codegen/instructions/initFarmsForReserve.js.map +1 -1
  127. package/dist/idl_codegen/instructions/initLendingMarket.d.ts +1 -0
  128. package/dist/idl_codegen/instructions/initLendingMarket.d.ts.map +1 -0
  129. package/dist/idl_codegen/instructions/initLendingMarket.js.map +1 -1
  130. package/dist/idl_codegen/instructions/initObligation.d.ts +1 -0
  131. package/dist/idl_codegen/instructions/initObligation.d.ts.map +1 -0
  132. package/dist/idl_codegen/instructions/initObligation.js.map +1 -1
  133. package/dist/idl_codegen/instructions/initObligationFarmsForReserve.d.ts +1 -0
  134. package/dist/idl_codegen/instructions/initObligationFarmsForReserve.d.ts.map +1 -0
  135. package/dist/idl_codegen/instructions/initObligationFarmsForReserve.js.map +1 -1
  136. package/dist/idl_codegen/instructions/initReferrerStateAndShortUrl.d.ts +1 -0
  137. package/dist/idl_codegen/instructions/initReferrerStateAndShortUrl.d.ts.map +1 -0
  138. package/dist/idl_codegen/instructions/initReferrerStateAndShortUrl.js.map +1 -1
  139. package/dist/idl_codegen/instructions/initReferrerTokenState.d.ts +1 -0
  140. package/dist/idl_codegen/instructions/initReferrerTokenState.d.ts.map +1 -0
  141. package/dist/idl_codegen/instructions/initReferrerTokenState.js.map +1 -1
  142. package/dist/idl_codegen/instructions/initReserve.d.ts +1 -0
  143. package/dist/idl_codegen/instructions/initReserve.d.ts.map +1 -0
  144. package/dist/idl_codegen/instructions/initReserve.js.map +1 -1
  145. package/dist/idl_codegen/instructions/initUserMetadata.d.ts +1 -0
  146. package/dist/idl_codegen/instructions/initUserMetadata.d.ts.map +1 -0
  147. package/dist/idl_codegen/instructions/initUserMetadata.js.map +1 -1
  148. package/dist/idl_codegen/instructions/liquidateObligationAndRedeemReserveCollateral.d.ts +1 -0
  149. package/dist/idl_codegen/instructions/liquidateObligationAndRedeemReserveCollateral.d.ts.map +1 -0
  150. package/dist/idl_codegen/instructions/liquidateObligationAndRedeemReserveCollateral.js.map +1 -1
  151. package/dist/idl_codegen/instructions/redeemFees.d.ts +1 -0
  152. package/dist/idl_codegen/instructions/redeemFees.d.ts.map +1 -0
  153. package/dist/idl_codegen/instructions/redeemFees.js.map +1 -1
  154. package/dist/idl_codegen/instructions/redeemReserveCollateral.d.ts +1 -0
  155. package/dist/idl_codegen/instructions/redeemReserveCollateral.d.ts.map +1 -0
  156. package/dist/idl_codegen/instructions/redeemReserveCollateral.js.map +1 -1
  157. package/dist/idl_codegen/instructions/refreshObligation.d.ts +1 -0
  158. package/dist/idl_codegen/instructions/refreshObligation.d.ts.map +1 -0
  159. package/dist/idl_codegen/instructions/refreshObligation.js.map +1 -1
  160. package/dist/idl_codegen/instructions/refreshObligationFarmsForReserve.d.ts +1 -0
  161. package/dist/idl_codegen/instructions/refreshObligationFarmsForReserve.d.ts.map +1 -0
  162. package/dist/idl_codegen/instructions/refreshObligationFarmsForReserve.js.map +1 -1
  163. package/dist/idl_codegen/instructions/refreshReserve.d.ts +1 -0
  164. package/dist/idl_codegen/instructions/refreshReserve.d.ts.map +1 -0
  165. package/dist/idl_codegen/instructions/refreshReserve.js.map +1 -1
  166. package/dist/idl_codegen/instructions/refreshReservesBatch.d.ts +1 -0
  167. package/dist/idl_codegen/instructions/refreshReservesBatch.d.ts.map +1 -0
  168. package/dist/idl_codegen/instructions/refreshReservesBatch.js.map +1 -1
  169. package/dist/idl_codegen/instructions/repayObligationLiquidity.d.ts +1 -0
  170. package/dist/idl_codegen/instructions/repayObligationLiquidity.d.ts.map +1 -0
  171. package/dist/idl_codegen/instructions/repayObligationLiquidity.js.map +1 -1
  172. package/dist/idl_codegen/instructions/requestElevationGroup.d.ts +1 -0
  173. package/dist/idl_codegen/instructions/requestElevationGroup.d.ts.map +1 -0
  174. package/dist/idl_codegen/instructions/requestElevationGroup.js.map +1 -1
  175. package/dist/idl_codegen/instructions/socializeLoss.d.ts +1 -0
  176. package/dist/idl_codegen/instructions/socializeLoss.d.ts.map +1 -0
  177. package/dist/idl_codegen/instructions/socializeLoss.js.map +1 -1
  178. package/dist/idl_codegen/instructions/updateEntireReserveConfig.d.ts +1 -0
  179. package/dist/idl_codegen/instructions/updateEntireReserveConfig.d.ts.map +1 -0
  180. package/dist/idl_codegen/instructions/updateEntireReserveConfig.js.map +1 -1
  181. package/dist/idl_codegen/instructions/updateLendingMarket.d.ts +1 -0
  182. package/dist/idl_codegen/instructions/updateLendingMarket.d.ts.map +1 -0
  183. package/dist/idl_codegen/instructions/updateLendingMarket.js.map +1 -1
  184. package/dist/idl_codegen/instructions/updateLendingMarketOwner.d.ts +1 -0
  185. package/dist/idl_codegen/instructions/updateLendingMarketOwner.d.ts.map +1 -0
  186. package/dist/idl_codegen/instructions/updateLendingMarketOwner.js.map +1 -1
  187. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts +1 -0
  188. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts.map +1 -0
  189. package/dist/idl_codegen/instructions/updateReserveConfig.js.map +1 -1
  190. package/dist/idl_codegen/instructions/updateSingleReserveConfig.d.ts +1 -0
  191. package/dist/idl_codegen/instructions/updateSingleReserveConfig.d.ts.map +1 -0
  192. package/dist/idl_codegen/instructions/updateSingleReserveConfig.js.map +1 -1
  193. package/dist/idl_codegen/instructions/withdrawObligationCollateral.d.ts +1 -0
  194. package/dist/idl_codegen/instructions/withdrawObligationCollateral.d.ts.map +1 -0
  195. package/dist/idl_codegen/instructions/withdrawObligationCollateral.js.map +1 -1
  196. package/dist/idl_codegen/instructions/withdrawObligationCollateralAndRedeemReserveCollateral.d.ts +1 -0
  197. package/dist/idl_codegen/instructions/withdrawObligationCollateralAndRedeemReserveCollateral.d.ts.map +1 -0
  198. package/dist/idl_codegen/instructions/withdrawObligationCollateralAndRedeemReserveCollateral.js.map +1 -1
  199. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts +1 -0
  200. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts.map +1 -0
  201. package/dist/idl_codegen/instructions/withdrawProtocolFee.js.map +1 -1
  202. package/dist/idl_codegen/instructions/withdrawReferrerFees.d.ts +1 -0
  203. package/dist/idl_codegen/instructions/withdrawReferrerFees.d.ts.map +1 -0
  204. package/dist/idl_codegen/instructions/withdrawReferrerFees.js.map +1 -1
  205. package/dist/idl_codegen/programId.d.ts +1 -0
  206. package/dist/idl_codegen/programId.d.ts.map +1 -0
  207. package/dist/idl_codegen/programId.js.map +1 -1
  208. package/dist/idl_codegen/types/AssetTier.d.ts +1 -0
  209. package/dist/idl_codegen/types/AssetTier.d.ts.map +1 -0
  210. package/dist/idl_codegen/types/AssetTier.js +12 -18
  211. package/dist/idl_codegen/types/AssetTier.js.map +1 -1
  212. package/dist/idl_codegen/types/BigFractionBytes.d.ts +1 -0
  213. package/dist/idl_codegen/types/BigFractionBytes.d.ts.map +1 -0
  214. package/dist/idl_codegen/types/BigFractionBytes.js +2 -0
  215. package/dist/idl_codegen/types/BigFractionBytes.js.map +1 -1
  216. package/dist/idl_codegen/types/BorrowRateCurve.d.ts +1 -0
  217. package/dist/idl_codegen/types/BorrowRateCurve.d.ts.map +1 -0
  218. package/dist/idl_codegen/types/BorrowRateCurve.js +2 -1
  219. package/dist/idl_codegen/types/BorrowRateCurve.js.map +1 -1
  220. package/dist/idl_codegen/types/CurvePoint.d.ts +1 -0
  221. package/dist/idl_codegen/types/CurvePoint.d.ts.map +1 -0
  222. package/dist/idl_codegen/types/CurvePoint.js +2 -0
  223. package/dist/idl_codegen/types/CurvePoint.js.map +1 -1
  224. package/dist/idl_codegen/types/ElevationGroup.d.ts +1 -0
  225. package/dist/idl_codegen/types/ElevationGroup.d.ts.map +1 -0
  226. package/dist/idl_codegen/types/ElevationGroup.js +10 -0
  227. package/dist/idl_codegen/types/ElevationGroup.js.map +1 -1
  228. package/dist/idl_codegen/types/FeeCalculation.d.ts +1 -0
  229. package/dist/idl_codegen/types/FeeCalculation.d.ts.map +1 -0
  230. package/dist/idl_codegen/types/FeeCalculation.js +8 -12
  231. package/dist/idl_codegen/types/FeeCalculation.js.map +1 -1
  232. package/dist/idl_codegen/types/InitObligationArgs.d.ts +1 -0
  233. package/dist/idl_codegen/types/InitObligationArgs.d.ts.map +1 -0
  234. package/dist/idl_codegen/types/InitObligationArgs.js +2 -0
  235. package/dist/idl_codegen/types/InitObligationArgs.js.map +1 -1
  236. package/dist/idl_codegen/types/LastUpdate.d.ts +1 -0
  237. package/dist/idl_codegen/types/LastUpdate.d.ts.map +1 -0
  238. package/dist/idl_codegen/types/LastUpdate.js +7 -0
  239. package/dist/idl_codegen/types/LastUpdate.js.map +1 -1
  240. package/dist/idl_codegen/types/ObligationCollateral.d.ts +1 -0
  241. package/dist/idl_codegen/types/ObligationCollateral.d.ts.map +1 -0
  242. package/dist/idl_codegen/types/ObligationCollateral.js +14 -0
  243. package/dist/idl_codegen/types/ObligationCollateral.js.map +1 -1
  244. package/dist/idl_codegen/types/ObligationLiquidity.d.ts +1 -0
  245. package/dist/idl_codegen/types/ObligationLiquidity.d.ts.map +1 -0
  246. package/dist/idl_codegen/types/ObligationLiquidity.js +17 -1
  247. package/dist/idl_codegen/types/ObligationLiquidity.js.map +1 -1
  248. package/dist/idl_codegen/types/PriceHeuristic.d.ts +1 -0
  249. package/dist/idl_codegen/types/PriceHeuristic.d.ts.map +1 -0
  250. package/dist/idl_codegen/types/PriceHeuristic.js +6 -0
  251. package/dist/idl_codegen/types/PriceHeuristic.js.map +1 -1
  252. package/dist/idl_codegen/types/PythConfiguration.d.ts +1 -0
  253. package/dist/idl_codegen/types/PythConfiguration.d.ts.map +1 -0
  254. package/dist/idl_codegen/types/PythConfiguration.js +2 -0
  255. package/dist/idl_codegen/types/PythConfiguration.js.map +1 -1
  256. package/dist/idl_codegen/types/ReserveCollateral.d.ts +1 -0
  257. package/dist/idl_codegen/types/ReserveCollateral.d.ts.map +1 -0
  258. package/dist/idl_codegen/types/ReserveCollateral.js +8 -0
  259. package/dist/idl_codegen/types/ReserveCollateral.js.map +1 -1
  260. package/dist/idl_codegen/types/ReserveConfig.d.ts +1 -0
  261. package/dist/idl_codegen/types/ReserveConfig.d.ts.map +1 -0
  262. package/dist/idl_codegen/types/ReserveConfig.js +78 -5
  263. package/dist/idl_codegen/types/ReserveConfig.js.map +1 -1
  264. package/dist/idl_codegen/types/ReserveFarmKind.d.ts +1 -0
  265. package/dist/idl_codegen/types/ReserveFarmKind.d.ts.map +1 -0
  266. package/dist/idl_codegen/types/ReserveFarmKind.js +8 -12
  267. package/dist/idl_codegen/types/ReserveFarmKind.js.map +1 -1
  268. package/dist/idl_codegen/types/ReserveFees.d.ts +1 -0
  269. package/dist/idl_codegen/types/ReserveFees.d.ts.map +1 -0
  270. package/dist/idl_codegen/types/ReserveFees.js +16 -0
  271. package/dist/idl_codegen/types/ReserveFees.js.map +1 -1
  272. package/dist/idl_codegen/types/ReserveLiquidity.d.ts +1 -0
  273. package/dist/idl_codegen/types/ReserveLiquidity.d.ts.map +1 -0
  274. package/dist/idl_codegen/types/ReserveLiquidity.js +43 -1
  275. package/dist/idl_codegen/types/ReserveLiquidity.js.map +1 -1
  276. package/dist/idl_codegen/types/ReserveStatus.d.ts +1 -0
  277. package/dist/idl_codegen/types/ReserveStatus.d.ts.map +1 -0
  278. package/dist/idl_codegen/types/ReserveStatus.js +12 -18
  279. package/dist/idl_codegen/types/ReserveStatus.js.map +1 -1
  280. package/dist/idl_codegen/types/ScopeConfiguration.d.ts +1 -0
  281. package/dist/idl_codegen/types/ScopeConfiguration.d.ts.map +1 -0
  282. package/dist/idl_codegen/types/ScopeConfiguration.js +6 -0
  283. package/dist/idl_codegen/types/ScopeConfiguration.js.map +1 -1
  284. package/dist/idl_codegen/types/SwitchboardConfiguration.d.ts +1 -0
  285. package/dist/idl_codegen/types/SwitchboardConfiguration.d.ts.map +1 -0
  286. package/dist/idl_codegen/types/SwitchboardConfiguration.js +3 -0
  287. package/dist/idl_codegen/types/SwitchboardConfiguration.js.map +1 -1
  288. package/dist/idl_codegen/types/TokenInfo.d.ts +1 -0
  289. package/dist/idl_codegen/types/TokenInfo.d.ts.map +1 -0
  290. package/dist/idl_codegen/types/TokenInfo.js +27 -4
  291. package/dist/idl_codegen/types/TokenInfo.js.map +1 -1
  292. package/dist/idl_codegen/types/UpdateConfigMode.d.ts +1 -0
  293. package/dist/idl_codegen/types/UpdateConfigMode.d.ts.map +1 -0
  294. package/dist/idl_codegen/types/UpdateConfigMode.js +188 -282
  295. package/dist/idl_codegen/types/UpdateConfigMode.js.map +1 -1
  296. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.d.ts +1 -0
  297. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.d.ts.map +1 -0
  298. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.js +41 -33
  299. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.js.map +1 -1
  300. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts +1 -0
  301. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts.map +1 -0
  302. package/dist/idl_codegen/types/UpdateLendingMarketMode.js +72 -108
  303. package/dist/idl_codegen/types/UpdateLendingMarketMode.js.map +1 -1
  304. package/dist/idl_codegen/types/WithdrawalCaps.d.ts +1 -0
  305. package/dist/idl_codegen/types/WithdrawalCaps.d.ts.map +1 -0
  306. package/dist/idl_codegen/types/WithdrawalCaps.js +4 -0
  307. package/dist/idl_codegen/types/WithdrawalCaps.js.map +1 -1
  308. package/dist/idl_codegen/types/index.d.ts +1 -0
  309. package/dist/idl_codegen/types/index.d.ts.map +1 -0
  310. package/dist/idl_codegen/types/index.js.map +1 -1
  311. package/dist/idl_codegen/zero_padding/ObligationZP.d.ts +1 -0
  312. package/dist/idl_codegen/zero_padding/ObligationZP.d.ts.map +1 -0
  313. package/dist/idl_codegen/zero_padding/ObligationZP.js +83 -54
  314. package/dist/idl_codegen/zero_padding/ObligationZP.js.map +1 -1
  315. package/dist/idl_codegen/zero_padding/index.d.ts +1 -0
  316. package/dist/idl_codegen/zero_padding/index.d.ts.map +1 -0
  317. package/dist/idl_codegen/zero_padding/index.js.map +1 -1
  318. package/dist/idl_codegen_jupiter_perps/accounts/Pool.d.ts +1 -0
  319. package/dist/idl_codegen_jupiter_perps/accounts/Pool.d.ts.map +1 -0
  320. package/dist/idl_codegen_jupiter_perps/accounts/Pool.js +39 -42
  321. package/dist/idl_codegen_jupiter_perps/accounts/Pool.js.map +1 -1
  322. package/dist/idl_codegen_jupiter_perps/accounts/index.d.ts +1 -0
  323. package/dist/idl_codegen_jupiter_perps/accounts/index.d.ts.map +1 -0
  324. package/dist/idl_codegen_jupiter_perps/accounts/index.js.map +1 -1
  325. package/dist/idl_codegen_jupiter_perps/programId.d.ts +1 -0
  326. package/dist/idl_codegen_jupiter_perps/programId.d.ts.map +1 -0
  327. package/dist/idl_codegen_jupiter_perps/programId.js.map +1 -1
  328. package/dist/idl_codegen_jupiter_perps/types/Fees.d.ts +1 -0
  329. package/dist/idl_codegen_jupiter_perps/types/Fees.d.ts.map +1 -0
  330. package/dist/idl_codegen_jupiter_perps/types/Fees.js +9 -0
  331. package/dist/idl_codegen_jupiter_perps/types/Fees.js.map +1 -1
  332. package/dist/idl_codegen_jupiter_perps/types/Limit.d.ts +1 -0
  333. package/dist/idl_codegen_jupiter_perps/types/Limit.d.ts.map +1 -0
  334. package/dist/idl_codegen_jupiter_perps/types/Limit.js +3 -0
  335. package/dist/idl_codegen_jupiter_perps/types/Limit.js.map +1 -1
  336. package/dist/idl_codegen_jupiter_perps/types/PoolApr.d.ts +1 -0
  337. package/dist/idl_codegen_jupiter_perps/types/PoolApr.d.ts.map +1 -0
  338. package/dist/idl_codegen_jupiter_perps/types/PoolApr.js +3 -0
  339. package/dist/idl_codegen_jupiter_perps/types/PoolApr.js.map +1 -1
  340. package/dist/idl_codegen_jupiter_perps/types/index.d.ts +1 -0
  341. package/dist/idl_codegen_jupiter_perps/types/index.d.ts.map +1 -0
  342. package/dist/idl_codegen_jupiter_perps/types/index.js.map +1 -1
  343. package/dist/idl_codegen_kamino_vault/accounts/Reserve.d.ts +1 -0
  344. package/dist/idl_codegen_kamino_vault/accounts/Reserve.d.ts.map +1 -0
  345. package/dist/idl_codegen_kamino_vault/accounts/Reserve.js +58 -47
  346. package/dist/idl_codegen_kamino_vault/accounts/Reserve.js.map +1 -1
  347. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts +1 -0
  348. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts.map +1 -0
  349. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js +51 -47
  350. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js.map +1 -1
  351. package/dist/idl_codegen_kamino_vault/accounts/index.d.ts +1 -0
  352. package/dist/idl_codegen_kamino_vault/accounts/index.d.ts.map +1 -0
  353. package/dist/idl_codegen_kamino_vault/accounts/index.js.map +1 -1
  354. package/dist/idl_codegen_kamino_vault/errors/anchor.d.ts +1 -0
  355. package/dist/idl_codegen_kamino_vault/errors/anchor.d.ts.map +1 -0
  356. package/dist/idl_codegen_kamino_vault/errors/anchor.js +270 -216
  357. package/dist/idl_codegen_kamino_vault/errors/anchor.js.map +1 -1
  358. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts +1 -0
  359. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts.map +1 -0
  360. package/dist/idl_codegen_kamino_vault/errors/custom.js +120 -96
  361. package/dist/idl_codegen_kamino_vault/errors/custom.js.map +1 -1
  362. package/dist/idl_codegen_kamino_vault/errors/index.d.ts +1 -0
  363. package/dist/idl_codegen_kamino_vault/errors/index.d.ts.map +1 -0
  364. package/dist/idl_codegen_kamino_vault/errors/index.js.map +1 -1
  365. package/dist/idl_codegen_kamino_vault/instructions/deposit.d.ts +1 -0
  366. package/dist/idl_codegen_kamino_vault/instructions/deposit.d.ts.map +1 -0
  367. package/dist/idl_codegen_kamino_vault/instructions/deposit.js.map +1 -1
  368. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts +1 -0
  369. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts.map +1 -0
  370. package/dist/idl_codegen_kamino_vault/instructions/index.js.map +1 -1
  371. package/dist/idl_codegen_kamino_vault/instructions/initVault.d.ts +1 -0
  372. package/dist/idl_codegen_kamino_vault/instructions/initVault.d.ts.map +1 -0
  373. package/dist/idl_codegen_kamino_vault/instructions/initVault.js.map +1 -1
  374. package/dist/idl_codegen_kamino_vault/instructions/invest.d.ts +1 -0
  375. package/dist/idl_codegen_kamino_vault/instructions/invest.d.ts.map +1 -0
  376. package/dist/idl_codegen_kamino_vault/instructions/invest.js.map +1 -1
  377. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.d.ts +1 -0
  378. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.d.ts.map +1 -0
  379. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.js.map +1 -1
  380. package/dist/idl_codegen_kamino_vault/instructions/withdraw.d.ts +1 -0
  381. package/dist/idl_codegen_kamino_vault/instructions/withdraw.d.ts.map +1 -0
  382. package/dist/idl_codegen_kamino_vault/instructions/withdraw.js.map +1 -1
  383. package/dist/idl_codegen_kamino_vault/programId.d.ts +1 -0
  384. package/dist/idl_codegen_kamino_vault/programId.d.ts.map +1 -0
  385. package/dist/idl_codegen_kamino_vault/programId.js.map +1 -1
  386. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.d.ts +1 -0
  387. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.d.ts.map +1 -0
  388. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.js +2 -0
  389. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.js.map +1 -1
  390. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.d.ts +1 -0
  391. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.d.ts.map +1 -0
  392. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.js +2 -1
  393. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.js.map +1 -1
  394. package/dist/idl_codegen_kamino_vault/types/CurvePoint.d.ts +1 -0
  395. package/dist/idl_codegen_kamino_vault/types/CurvePoint.d.ts.map +1 -0
  396. package/dist/idl_codegen_kamino_vault/types/CurvePoint.js +2 -0
  397. package/dist/idl_codegen_kamino_vault/types/CurvePoint.js.map +1 -1
  398. package/dist/idl_codegen_kamino_vault/types/LastUpdate.d.ts +1 -0
  399. package/dist/idl_codegen_kamino_vault/types/LastUpdate.d.ts.map +1 -0
  400. package/dist/idl_codegen_kamino_vault/types/LastUpdate.js +7 -0
  401. package/dist/idl_codegen_kamino_vault/types/LastUpdate.js.map +1 -1
  402. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.d.ts +1 -0
  403. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.d.ts.map +1 -0
  404. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.js +6 -0
  405. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.js.map +1 -1
  406. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.d.ts +1 -0
  407. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.d.ts.map +1 -0
  408. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.js +2 -0
  409. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.js.map +1 -1
  410. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.d.ts +1 -0
  411. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.d.ts.map +1 -0
  412. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.js +8 -0
  413. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.js.map +1 -1
  414. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.d.ts +1 -0
  415. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.d.ts.map +1 -0
  416. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.js +77 -5
  417. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.js.map +1 -1
  418. package/dist/idl_codegen_kamino_vault/types/ReserveFees.d.ts +1 -0
  419. package/dist/idl_codegen_kamino_vault/types/ReserveFees.d.ts.map +1 -0
  420. package/dist/idl_codegen_kamino_vault/types/ReserveFees.js +16 -0
  421. package/dist/idl_codegen_kamino_vault/types/ReserveFees.js.map +1 -1
  422. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.d.ts +1 -0
  423. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.d.ts.map +1 -0
  424. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.js +41 -1
  425. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.js.map +1 -1
  426. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.d.ts +1 -0
  427. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.d.ts.map +1 -0
  428. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.js +6 -0
  429. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.js.map +1 -1
  430. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.d.ts +1 -0
  431. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.d.ts.map +1 -0
  432. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.js +3 -0
  433. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.js.map +1 -1
  434. package/dist/idl_codegen_kamino_vault/types/TokenInfo.d.ts +1 -0
  435. package/dist/idl_codegen_kamino_vault/types/TokenInfo.d.ts.map +1 -0
  436. package/dist/idl_codegen_kamino_vault/types/TokenInfo.js +27 -4
  437. package/dist/idl_codegen_kamino_vault/types/TokenInfo.js.map +1 -1
  438. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.d.ts +1 -0
  439. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.d.ts.map +1 -0
  440. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.js +8 -0
  441. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.js.map +1 -1
  442. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.d.ts +1 -0
  443. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.d.ts.map +1 -0
  444. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.js +4 -0
  445. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.js.map +1 -1
  446. package/dist/idl_codegen_kamino_vault/types/index.d.ts +1 -0
  447. package/dist/idl_codegen_kamino_vault/types/index.d.ts.map +1 -0
  448. package/dist/idl_codegen_kamino_vault/types/index.js.map +1 -1
  449. package/dist/index.d.ts +1 -0
  450. package/dist/index.d.ts.map +1 -0
  451. package/dist/index.js.map +1 -1
  452. package/dist/lending_operations/index.d.ts +1 -0
  453. package/dist/lending_operations/index.d.ts.map +1 -0
  454. package/dist/lending_operations/index.js.map +1 -1
  455. package/dist/lending_operations/repay_with_collateral_calcs.d.ts +1 -0
  456. package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -0
  457. package/dist/lending_operations/repay_with_collateral_calcs.js +1 -1
  458. package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
  459. package/dist/lending_operations/repay_with_collateral_operations.d.ts +1 -0
  460. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -0
  461. package/dist/lending_operations/repay_with_collateral_operations.js +15 -24
  462. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  463. package/dist/leverage/calcs.d.ts +1 -0
  464. package/dist/leverage/calcs.d.ts.map +1 -0
  465. package/dist/leverage/calcs.js +119 -132
  466. package/dist/leverage/calcs.js.map +1 -1
  467. package/dist/leverage/index.d.ts +1 -0
  468. package/dist/leverage/index.d.ts.map +1 -0
  469. package/dist/leverage/index.js.map +1 -1
  470. package/dist/leverage/instructions.d.ts +1 -0
  471. package/dist/leverage/instructions.d.ts.map +1 -0
  472. package/dist/leverage/instructions.js.map +1 -1
  473. package/dist/leverage/operations.d.ts +1 -0
  474. package/dist/leverage/operations.d.ts.map +1 -0
  475. package/dist/leverage/operations.js +75 -84
  476. package/dist/leverage/operations.js.map +1 -1
  477. package/dist/leverage/utils.d.ts +1 -0
  478. package/dist/leverage/utils.d.ts.map +1 -0
  479. package/dist/leverage/utils.js +73 -88
  480. package/dist/leverage/utils.js.map +1 -1
  481. package/dist/lib.d.ts +1 -0
  482. package/dist/lib.d.ts.map +1 -0
  483. package/dist/lib.js.map +1 -1
  484. package/dist/referrals/index.d.ts +1 -0
  485. package/dist/referrals/index.d.ts.map +1 -0
  486. package/dist/referrals/index.js.map +1 -1
  487. package/dist/referrals/instructions.d.ts +1 -0
  488. package/dist/referrals/instructions.d.ts.map +1 -0
  489. package/dist/referrals/instructions.js +8 -17
  490. package/dist/referrals/instructions.js.map +1 -1
  491. package/dist/referrals/operations.d.ts +2 -1
  492. package/dist/referrals/operations.d.ts.map +1 -0
  493. package/dist/referrals/operations.js +119 -143
  494. package/dist/referrals/operations.js.map +1 -1
  495. package/dist/utils/ObligationType.d.ts +1 -0
  496. package/dist/utils/ObligationType.d.ts.map +1 -0
  497. package/dist/utils/ObligationType.js +16 -7
  498. package/dist/utils/ObligationType.js.map +1 -1
  499. package/dist/utils/api.d.ts +1 -0
  500. package/dist/utils/api.d.ts.map +1 -0
  501. package/dist/utils/api.js +10 -21
  502. package/dist/utils/api.js.map +1 -1
  503. package/dist/utils/ata.d.ts +1 -0
  504. package/dist/utils/ata.d.ts.map +1 -0
  505. package/dist/utils/ata.js +25 -38
  506. package/dist/utils/ata.js.map +1 -1
  507. package/dist/utils/constants.d.ts +1 -0
  508. package/dist/utils/constants.d.ts.map +1 -0
  509. package/dist/utils/constants.js +1 -1
  510. package/dist/utils/constants.js.map +1 -1
  511. package/dist/utils/idl.d.ts +1 -0
  512. package/dist/utils/idl.d.ts.map +1 -0
  513. package/dist/utils/idl.js.map +1 -1
  514. package/dist/utils/index.d.ts +1 -0
  515. package/dist/utils/index.d.ts.map +1 -0
  516. package/dist/utils/index.js.map +1 -1
  517. package/dist/utils/instruction.d.ts +1 -0
  518. package/dist/utils/instruction.d.ts.map +1 -0
  519. package/dist/utils/instruction.js +116 -143
  520. package/dist/utils/instruction.js.map +1 -1
  521. package/dist/utils/kamino.d.ts +1 -0
  522. package/dist/utils/kamino.d.ts.map +1 -0
  523. package/dist/utils/kamino.js +4 -15
  524. package/dist/utils/kamino.js.map +1 -1
  525. package/dist/utils/layout.d.ts +1 -0
  526. package/dist/utils/layout.d.ts.map +1 -0
  527. package/dist/utils/layout.js.map +1 -1
  528. package/dist/utils/lookupTable.d.ts +1 -0
  529. package/dist/utils/lookupTable.d.ts.map +1 -0
  530. package/dist/utils/lookupTable.js +14 -27
  531. package/dist/utils/lookupTable.js.map +1 -1
  532. package/dist/utils/managerTypes.d.ts +1 -0
  533. package/dist/utils/managerTypes.d.ts.map +1 -0
  534. package/dist/utils/managerTypes.js +31 -2
  535. package/dist/utils/managerTypes.js.map +1 -1
  536. package/dist/utils/oracle.d.ts +1 -0
  537. package/dist/utils/oracle.d.ts.map +1 -0
  538. package/dist/utils/oracle.js +70 -83
  539. package/dist/utils/oracle.js.map +1 -1
  540. package/dist/utils/pubkey.d.ts +1 -0
  541. package/dist/utils/pubkey.d.ts.map +1 -0
  542. package/dist/utils/pubkey.js +7 -9
  543. package/dist/utils/pubkey.js.map +1 -1
  544. package/dist/utils/rpc.d.ts +1 -0
  545. package/dist/utils/rpc.d.ts.map +1 -0
  546. package/dist/utils/rpc.js +48 -70
  547. package/dist/utils/rpc.js.map +1 -1
  548. package/dist/utils/seeds.d.ts +1 -0
  549. package/dist/utils/seeds.d.ts.map +1 -0
  550. package/dist/utils/seeds.js.map +1 -1
  551. package/dist/utils/sendTransactionsUtils.d.ts +1 -0
  552. package/dist/utils/sendTransactionsUtils.d.ts.map +1 -0
  553. package/dist/utils/sendTransactionsUtils.js +82 -82
  554. package/dist/utils/sendTransactionsUtils.js.map +1 -1
  555. package/dist/utils/slots.d.ts +1 -0
  556. package/dist/utils/slots.d.ts.map +1 -0
  557. package/dist/utils/slots.js.map +1 -1
  558. package/dist/utils/syncNative.d.ts +1 -0
  559. package/dist/utils/syncNative.d.ts.map +1 -0
  560. package/dist/utils/syncNative.js.map +1 -1
  561. package/dist/utils/userMetadata.d.ts +1 -0
  562. package/dist/utils/userMetadata.d.ts.map +1 -0
  563. package/dist/utils/userMetadata.js +40 -52
  564. package/dist/utils/userMetadata.js.map +1 -1
  565. package/package.json +9 -3
  566. package/src/classes/action.ts +2884 -0
  567. package/src/classes/curve.ts +29 -0
  568. package/src/classes/fraction.ts +65 -0
  569. package/src/classes/index.ts +10 -0
  570. package/src/classes/jupiterPerps.ts +14 -0
  571. package/src/classes/manager.ts +746 -0
  572. package/src/classes/market.ts +1459 -0
  573. package/src/classes/obligation.ts +1315 -0
  574. package/src/classes/reserve.ts +1980 -0
  575. package/src/classes/shared.ts +57 -0
  576. package/src/classes/utils.ts +192 -0
  577. package/src/classes/vault.ts +808 -0
  578. package/src/client.ts +446 -0
  579. package/src/client_kamino_manager.ts +791 -0
  580. package/src/global.d.ts +1 -0
  581. package/src/idl_codegen/accounts/LendingMarket.ts +364 -0
  582. package/src/idl_codegen/accounts/Obligation.ts +349 -0
  583. package/src/idl_codegen/accounts/ReferrerState.ts +97 -0
  584. package/src/idl_codegen/accounts/ReferrerTokenState.ts +145 -0
  585. package/src/idl_codegen/accounts/Reserve.ts +248 -0
  586. package/src/idl_codegen/accounts/ShortUrl.ts +97 -0
  587. package/src/idl_codegen/accounts/UserMetadata.ts +142 -0
  588. package/src/idl_codegen/accounts/UserState.ts +301 -0
  589. package/src/idl_codegen/accounts/index.ts +19 -0
  590. package/src/idl_codegen/errors/anchor.ts +773 -0
  591. package/src/idl_codegen/errors/custom.ts +1633 -0
  592. package/src/idl_codegen/errors/index.ts +62 -0
  593. package/src/idl_codegen/instructions/borrowObligationLiquidity.ts +82 -0
  594. package/src/idl_codegen/instructions/deleteReferrerStateAndShortUrl.ts +30 -0
  595. package/src/idl_codegen/instructions/depositObligationCollateral.ts +62 -0
  596. package/src/idl_codegen/instructions/depositReserveLiquidity.ts +90 -0
  597. package/src/idl_codegen/instructions/depositReserveLiquidityAndObligationCollateral.ts +98 -0
  598. package/src/idl_codegen/instructions/flashBorrowReserveLiquidity.ts +82 -0
  599. package/src/idl_codegen/instructions/flashRepayReserveLiquidity.ts +83 -0
  600. package/src/idl_codegen/instructions/idlMissingTypes.ts +62 -0
  601. package/src/idl_codegen/instructions/index.ts +138 -0
  602. package/src/idl_codegen/instructions/initFarmsForReserve.ts +62 -0
  603. package/src/idl_codegen/instructions/initLendingMarket.ts +50 -0
  604. package/src/idl_codegen/instructions/initObligation.ts +52 -0
  605. package/src/idl_codegen/instructions/initObligationFarmsForReserve.ts +60 -0
  606. package/src/idl_codegen/instructions/initReferrerStateAndShortUrl.ts +50 -0
  607. package/src/idl_codegen/instructions/initReferrerTokenState.ts +46 -0
  608. package/src/idl_codegen/instructions/initReserve.ts +74 -0
  609. package/src/idl_codegen/instructions/initUserMetadata.ts +50 -0
  610. package/src/idl_codegen/instructions/liquidateObligationAndRedeemReserveCollateral.ts +139 -0
  611. package/src/idl_codegen/instructions/redeemFees.ts +50 -0
  612. package/src/idl_codegen/instructions/redeemReserveCollateral.ts +94 -0
  613. package/src/idl_codegen/instructions/refreshObligation.ts +24 -0
  614. package/src/idl_codegen/instructions/refreshObligationFarmsForReserve.ts +62 -0
  615. package/src/idl_codegen/instructions/refreshReserve.ts +40 -0
  616. package/src/idl_codegen/instructions/refreshReservesBatch.ts +29 -0
  617. package/src/idl_codegen/instructions/repayObligationLiquidity.ts +64 -0
  618. package/src/idl_codegen/instructions/requestElevationGroup.ts +40 -0
  619. package/src/idl_codegen/instructions/socializeLoss.ts +48 -0
  620. package/src/idl_codegen/instructions/updateEntireReserveConfig.ts +45 -0
  621. package/src/idl_codegen/instructions/updateLendingMarket.ts +43 -0
  622. package/src/idl_codegen/instructions/updateLendingMarketOwner.ts +28 -0
  623. package/src/idl_codegen/instructions/updateReserveConfig.ts +52 -0
  624. package/src/idl_codegen/instructions/updateSingleReserveConfig.ts +48 -0
  625. package/src/idl_codegen/instructions/withdrawObligationCollateral.ts +68 -0
  626. package/src/idl_codegen/instructions/withdrawObligationCollateralAndRedeemReserveCollateral.ts +102 -0
  627. package/src/idl_codegen/instructions/withdrawProtocolFee.ts +62 -0
  628. package/src/idl_codegen/instructions/withdrawReferrerFees.ts +54 -0
  629. package/src/idl_codegen/programId.ts +13 -0
  630. package/src/idl_codegen/types/AssetTier.ts +118 -0
  631. package/src/idl_codegen/types/BigFractionBytes.ts +67 -0
  632. package/src/idl_codegen/types/BorrowRateCurve.ts +60 -0
  633. package/src/idl_codegen/types/CurvePoint.ts +64 -0
  634. package/src/idl_codegen/types/ElevationGroup.ts +133 -0
  635. package/src/idl_codegen/types/FeeCalculation.ts +90 -0
  636. package/src/idl_codegen/types/InitObligationArgs.ts +61 -0
  637. package/src/idl_codegen/types/LastUpdate.ts +95 -0
  638. package/src/idl_codegen/types/ObligationCollateral.ts +128 -0
  639. package/src/idl_codegen/types/ObligationLiquidity.ts +159 -0
  640. package/src/idl_codegen/types/PriceHeuristic.ts +81 -0
  641. package/src/idl_codegen/types/PythConfiguration.ts +56 -0
  642. package/src/idl_codegen/types/ReserveCollateral.ts +104 -0
  643. package/src/idl_codegen/types/ReserveConfig.ts +467 -0
  644. package/src/idl_codegen/types/ReserveFarmKind.ts +90 -0
  645. package/src/idl_codegen/types/ReserveFees.ts +122 -0
  646. package/src/idl_codegen/types/ReserveLiquidity.ts +286 -0
  647. package/src/idl_codegen/types/ReserveStatus.ts +120 -0
  648. package/src/idl_codegen/types/ScopeConfiguration.ts +85 -0
  649. package/src/idl_codegen/types/SwitchboardConfiguration.ts +67 -0
  650. package/src/idl_codegen/types/TokenInfo.ts +190 -0
  651. package/src/idl_codegen/types/UpdateConfigMode.ts +1440 -0
  652. package/src/idl_codegen/types/UpdateLendingMarketConfigValue.ts +376 -0
  653. package/src/idl_codegen/types/UpdateLendingMarketMode.ts +570 -0
  654. package/src/idl_codegen/types/WithdrawalCaps.ts +86 -0
  655. package/src/idl_codegen/types/index.ts +276 -0
  656. package/src/idl_codegen/zero_padding/ObligationZP.ts +186 -0
  657. package/src/idl_codegen/zero_padding/index.ts +1 -0
  658. package/src/idl_codegen_jupiter_perps/accounts/Pool.ts +155 -0
  659. package/src/idl_codegen_jupiter_perps/accounts/index.ts +2 -0
  660. package/src/idl_codegen_jupiter_perps/programId.ts +7 -0
  661. package/src/idl_codegen_jupiter_perps/types/Fees.ts +130 -0
  662. package/src/idl_codegen_jupiter_perps/types/Limit.ts +72 -0
  663. package/src/idl_codegen_jupiter_perps/types/PoolApr.ts +69 -0
  664. package/src/idl_codegen_jupiter_perps/types/index.ts +6 -0
  665. package/src/idl_codegen_kamino_vault/accounts/Reserve.ts +221 -0
  666. package/src/idl_codegen_kamino_vault/accounts/VaultState.ts +214 -0
  667. package/src/idl_codegen_kamino_vault/accounts/index.ts +4 -0
  668. package/src/idl_codegen_kamino_vault/errors/anchor.ts +764 -0
  669. package/src/idl_codegen_kamino_vault/errors/custom.ts +344 -0
  670. package/src/idl_codegen_kamino_vault/errors/index.ts +49 -0
  671. package/src/idl_codegen_kamino_vault/instructions/deposit.ts +54 -0
  672. package/src/idl_codegen_kamino_vault/instructions/index.ts +10 -0
  673. package/src/idl_codegen_kamino_vault/instructions/initVault.ts +35 -0
  674. package/src/idl_codegen_kamino_vault/instructions/invest.ts +60 -0
  675. package/src/idl_codegen_kamino_vault/instructions/updateReserveAllocation.ts +58 -0
  676. package/src/idl_codegen_kamino_vault/instructions/withdraw.ts +81 -0
  677. package/src/idl_codegen_kamino_vault/programId.ts +7 -0
  678. package/src/idl_codegen_kamino_vault/types/BigFractionBytes.ts +61 -0
  679. package/src/idl_codegen_kamino_vault/types/BorrowRateCurve.ts +55 -0
  680. package/src/idl_codegen_kamino_vault/types/CurvePoint.ts +61 -0
  681. package/src/idl_codegen_kamino_vault/types/LastUpdate.ts +90 -0
  682. package/src/idl_codegen_kamino_vault/types/PriceHeuristic.ts +78 -0
  683. package/src/idl_codegen_kamino_vault/types/PythConfiguration.ts +56 -0
  684. package/src/idl_codegen_kamino_vault/types/ReserveCollateral.ts +104 -0
  685. package/src/idl_codegen_kamino_vault/types/ReserveConfig.ts +426 -0
  686. package/src/idl_codegen_kamino_vault/types/ReserveFees.ts +118 -0
  687. package/src/idl_codegen_kamino_vault/types/ReserveLiquidity.ts +268 -0
  688. package/src/idl_codegen_kamino_vault/types/ScopeConfiguration.ts +85 -0
  689. package/src/idl_codegen_kamino_vault/types/SwitchboardConfiguration.ts +64 -0
  690. package/src/idl_codegen_kamino_vault/types/TokenInfo.ts +172 -0
  691. package/src/idl_codegen_kamino_vault/types/VaultAllocation.ts +115 -0
  692. package/src/idl_codegen_kamino_vault/types/WithdrawalCaps.ts +86 -0
  693. package/src/idl_codegen_kamino_vault/types/index.ts +30 -0
  694. package/src/index.ts +1 -0
  695. package/src/lending_operations/index.ts +2 -0
  696. package/src/lending_operations/repay_with_collateral_calcs.ts +71 -0
  697. package/src/lending_operations/repay_with_collateral_operations.ts +318 -0
  698. package/src/leverage/calcs.ts +465 -0
  699. package/src/leverage/index.ts +4 -0
  700. package/src/leverage/instructions.ts +144 -0
  701. package/src/leverage/operations.ts +1814 -0
  702. package/src/leverage/utils.ts +273 -0
  703. package/src/lib.ts +9 -0
  704. package/src/referrals/index.ts +2 -0
  705. package/src/referrals/instructions.ts +114 -0
  706. package/src/referrals/operations.ts +325 -0
  707. package/src/utils/ObligationType.ts +171 -0
  708. package/src/utils/api.ts +59 -0
  709. package/src/utils/ata.ts +195 -0
  710. package/src/utils/constants.ts +81 -0
  711. package/src/utils/idl.ts +4 -0
  712. package/src/utils/index.ts +16 -0
  713. package/src/utils/instruction.ts +258 -0
  714. package/src/utils/kamino.ts +12 -0
  715. package/src/utils/layout.ts +118 -0
  716. package/src/utils/lookupTable.ts +55 -0
  717. package/src/utils/managerTypes.ts +456 -0
  718. package/src/utils/oracle.ts +338 -0
  719. package/src/utils/pubkey.ts +261 -0
  720. package/src/utils/rpc.ts +108 -0
  721. package/src/utils/seeds.ts +183 -0
  722. package/src/utils/sendTransactionsUtils.ts +207 -0
  723. package/src/utils/slots.ts +28 -0
  724. package/src/utils/syncNative.ts +22 -0
  725. package/src/utils/userMetadata.ts +401 -0
@@ -0,0 +1,2884 @@
1
+ import {
2
+ Connection,
3
+ PublicKey,
4
+ RpcResponseAndContext,
5
+ SimulatedTransactionResponse,
6
+ SystemProgram,
7
+ SYSVAR_INSTRUCTIONS_PUBKEY,
8
+ SYSVAR_RENT_PUBKEY,
9
+ Transaction,
10
+ TransactionInstruction,
11
+ TransactionSignature,
12
+ } from '@solana/web3.js';
13
+ import {
14
+ ASSOCIATED_TOKEN_PROGRAM_ID,
15
+ NATIVE_MINT,
16
+ TOKEN_PROGRAM_ID,
17
+ createCloseAccountInstruction,
18
+ } from '@solana/spl-token';
19
+ import BN from 'bn.js';
20
+ import Decimal from 'decimal.js';
21
+ import {
22
+ borrowObligationLiquidity,
23
+ depositObligationCollateral,
24
+ depositReserveLiquidity,
25
+ depositReserveLiquidityAndObligationCollateral,
26
+ initObligation,
27
+ initObligationFarmsForReserve,
28
+ InitObligationFarmsForReserveAccounts,
29
+ InitObligationFarmsForReserveArgs,
30
+ initReferrerTokenState,
31
+ initUserMetadata,
32
+ liquidateObligationAndRedeemReserveCollateral,
33
+ redeemReserveCollateral,
34
+ refreshObligation,
35
+ refreshObligationFarmsForReserve,
36
+ RefreshObligationFarmsForReserveAccounts,
37
+ RefreshObligationFarmsForReserveArgs,
38
+ refreshReserve,
39
+ repayObligationLiquidity,
40
+ requestElevationGroup,
41
+ RequestElevationGroupAccounts,
42
+ RequestElevationGroupArgs,
43
+ withdrawObligationCollateralAndRedeemReserveCollateral,
44
+ withdrawReferrerFees,
45
+ } from '../idl_codegen/instructions';
46
+ import {
47
+ buildComputeBudgetIx,
48
+ createAssociatedTokenAccountIdempotentInstruction,
49
+ ObligationType,
50
+ syncNative,
51
+ U64_MAX,
52
+ referrerTokenStatePda,
53
+ userMetadataPda,
54
+ getAtasWithCreateIxnsIfMissing,
55
+ checkIfAccountExists,
56
+ createLookupTableIx,
57
+ isNotNullPubkey,
58
+ PublicKeySet,
59
+ WRAPPED_SOL_MINT,
60
+ getAssociatedTokenAddress,
61
+ ScopeRefresh,
62
+ } from '../utils';
63
+ import { KaminoMarket } from './market';
64
+ import { KaminoObligation } from './obligation';
65
+ import { KaminoReserve } from './reserve';
66
+ import { ReserveFarmKind } from '../idl_codegen/types';
67
+ import { farmsId } from '@hubbleprotocol/farms-sdk';
68
+ import { Reserve } from '../idl_codegen/accounts';
69
+ import { VanillaObligation } from '../utils/ObligationType';
70
+ import { PROGRAM_ID } from '../lib';
71
+ import { U16_MAX } from '@hubbleprotocol/scope-sdk';
72
+
73
+ export const POSITION_LIMIT = 10;
74
+ export const BORROWS_LIMIT = 5;
75
+ export const DEPOSITS_LIMIT = 8;
76
+
77
+ const SOL_PADDING_FOR_INTEREST = new BN('1000000');
78
+
79
+ export type ActionType =
80
+ | 'deposit'
81
+ | 'borrow'
82
+ | 'withdraw'
83
+ | 'repay'
84
+ | 'mint'
85
+ | 'redeem'
86
+ | 'depositCollateral'
87
+ | 'liquidate'
88
+ | 'depositAndBorrow'
89
+ | 'repayAndWithdraw'
90
+ | 'refreshObligation'
91
+ | 'requestElevationGroup'
92
+ | 'withdrawReferrerFees';
93
+
94
+ export type AuxiliaryIx = 'setup' | 'inBetween' | 'cleanup';
95
+
96
+ export class KaminoAction {
97
+ kaminoMarket: KaminoMarket;
98
+
99
+ reserve: KaminoReserve;
100
+
101
+ outflowReserve: KaminoReserve | undefined;
102
+
103
+ owner: PublicKey;
104
+ payer: PublicKey;
105
+
106
+ obligation: KaminoObligation | null = null;
107
+
108
+ referrer: PublicKey;
109
+
110
+ userTokenAccountAddress: PublicKey;
111
+
112
+ userCollateralAccountAddress: PublicKey;
113
+
114
+ additionalTokenAccountAddress?: PublicKey;
115
+
116
+ /**
117
+ * Null unless the obligation is not passed
118
+ */
119
+ obligationType: ObligationType | null = null;
120
+
121
+ mint: PublicKey;
122
+
123
+ secondaryMint?: PublicKey;
124
+
125
+ positions?: number;
126
+
127
+ amount: BN;
128
+ outflowAmount?: BN;
129
+
130
+ setupIxs: Array<TransactionInstruction>;
131
+ setupIxsLabels: Array<string>;
132
+
133
+ inBetweenIxs: Array<TransactionInstruction>;
134
+ inBetweenIxsLabels: Array<string>;
135
+
136
+ lendingIxs: Array<TransactionInstruction>;
137
+ lendingIxsLabels: Array<string>;
138
+
139
+ cleanupIxs: Array<TransactionInstruction>;
140
+ cleanupIxsLabels: Array<string>;
141
+
142
+ preTxnIxs: Array<TransactionInstruction>;
143
+ preTxnIxsLabels: Array<string>;
144
+
145
+ postTxnIxs: Array<TransactionInstruction>;
146
+ postTxnIxsLabels: Array<string>;
147
+
148
+ refreshFarmsCleanupTxnIxs: Array<TransactionInstruction>;
149
+ refreshFarmsCleanupTxnIxsLabels: Array<string>;
150
+
151
+ depositReserves: Array<PublicKey>;
152
+ borrowReserves: Array<PublicKey>;
153
+
154
+ preLoadedDepositReservesSameTx: Array<PublicKey>;
155
+ preLoadedBorrowReservesSameTx: Array<PublicKey>;
156
+
157
+ currentSlot: number;
158
+
159
+ private constructor(
160
+ kaminoMarket: KaminoMarket,
161
+ owner: PublicKey,
162
+ obligation: KaminoObligation | ObligationType | null,
163
+ userTokenAccountAddress: PublicKey,
164
+ userCollateralAccountAddress: PublicKey,
165
+ mint: PublicKey,
166
+ positions: number,
167
+ amount: string | BN,
168
+ depositReserves: Array<PublicKey>,
169
+ borrowReserves: Array<PublicKey>,
170
+ reserveState: KaminoReserve,
171
+ currentSlot: number,
172
+ secondaryMint?: PublicKey,
173
+ additionalTokenAccountAddress?: PublicKey,
174
+ outflowReserveState?: KaminoReserve,
175
+ outflowAmount?: string | BN,
176
+ referrer?: PublicKey,
177
+ payer?: PublicKey
178
+ ) {
179
+ if (obligation instanceof KaminoObligation) {
180
+ this.obligation = obligation;
181
+ } else if (obligation !== null) {
182
+ this.obligationType = obligation;
183
+ }
184
+
185
+ this.kaminoMarket = kaminoMarket;
186
+ this.owner = owner;
187
+ this.payer = payer ?? owner;
188
+ this.amount = new BN(amount);
189
+ this.mint = mint;
190
+ this.positions = positions;
191
+ this.userTokenAccountAddress = userTokenAccountAddress;
192
+ this.userCollateralAccountAddress = userCollateralAccountAddress;
193
+ this.setupIxs = [];
194
+ this.setupIxsLabels = [];
195
+ this.inBetweenIxs = [];
196
+ this.inBetweenIxsLabels = [];
197
+ this.lendingIxs = [];
198
+ this.lendingIxsLabels = [];
199
+ this.cleanupIxs = [];
200
+ this.cleanupIxsLabels = [];
201
+ this.preTxnIxs = [];
202
+ this.preTxnIxsLabels = [];
203
+ this.postTxnIxs = [];
204
+ this.postTxnIxsLabels = [];
205
+ this.refreshFarmsCleanupTxnIxs = [];
206
+ this.refreshFarmsCleanupTxnIxsLabels = [];
207
+ this.depositReserves = depositReserves;
208
+ this.borrowReserves = borrowReserves;
209
+ this.additionalTokenAccountAddress = additionalTokenAccountAddress;
210
+ this.secondaryMint = secondaryMint;
211
+ this.reserve = reserveState;
212
+ this.outflowReserve = outflowReserveState;
213
+ this.outflowAmount = outflowAmount ? new BN(outflowAmount) : undefined;
214
+ this.preLoadedDepositReservesSameTx = [];
215
+ this.preLoadedBorrowReservesSameTx = [];
216
+ this.referrer = referrer ? referrer : PublicKey.default;
217
+ this.currentSlot = currentSlot;
218
+ }
219
+
220
+ static async initialize(
221
+ action: ActionType,
222
+ amount: string | BN,
223
+ mint: PublicKey,
224
+ owner: PublicKey,
225
+ kaminoMarket: KaminoMarket,
226
+ obligation: KaminoObligation | ObligationType,
227
+ referrer: PublicKey = PublicKey.default,
228
+ currentSlot: number = 0,
229
+ payer?: PublicKey
230
+ ) {
231
+ const reserve = kaminoMarket.getReserveByMint(mint);
232
+ if (reserve === undefined) {
233
+ throw new Error(`Reserve ${mint} not found in market ${kaminoMarket.getAddress().toBase58()}`);
234
+ }
235
+
236
+ const { userTokenAccountAddress, userCollateralAccountAddress } = KaminoAction.getUserAccountAddresses(
237
+ payer ?? owner,
238
+ reserve.state
239
+ );
240
+
241
+ const { kaminoObligation, depositReserves, borrowReserves, distinctReserveCount } =
242
+ await KaminoAction.loadObligation(action, kaminoMarket, owner, reserve.address, obligation);
243
+
244
+ const referrerKey = await this.getReferrerKey(kaminoMarket, owner, kaminoObligation, referrer);
245
+
246
+ return new KaminoAction(
247
+ kaminoMarket,
248
+ owner,
249
+ kaminoObligation || obligation,
250
+ userTokenAccountAddress,
251
+ userCollateralAccountAddress,
252
+ mint,
253
+ distinctReserveCount,
254
+ amount,
255
+ depositReserves,
256
+ borrowReserves,
257
+ reserve,
258
+ currentSlot,
259
+ undefined,
260
+ undefined,
261
+ undefined,
262
+ undefined,
263
+ referrerKey,
264
+ payer
265
+ );
266
+ }
267
+
268
+ private static getUserAccountAddresses(owner: PublicKey, reserve: Reserve) {
269
+ const userTokenAccountAddress = getAssociatedTokenAddress(
270
+ reserve.liquidity.mintPubkey,
271
+ owner,
272
+ true,
273
+ reserve.liquidity.tokenProgram,
274
+ ASSOCIATED_TOKEN_PROGRAM_ID
275
+ );
276
+ const userCollateralAccountAddress = getAssociatedTokenAddress(
277
+ reserve.collateral.mintPubkey,
278
+ owner,
279
+ true,
280
+ TOKEN_PROGRAM_ID,
281
+ ASSOCIATED_TOKEN_PROGRAM_ID
282
+ );
283
+
284
+ return { userTokenAccountAddress, userCollateralAccountAddress };
285
+ }
286
+
287
+ private static async loadObligation(
288
+ action: ActionType,
289
+ kaminoMarket: KaminoMarket,
290
+ owner: PublicKey,
291
+ reserve: PublicKey,
292
+ obligation: KaminoObligation | ObligationType,
293
+ outflowReserve?: PublicKey
294
+ ) {
295
+ let kaminoObligation: KaminoObligation | null;
296
+ const depositReserves: Array<PublicKey> = [];
297
+ const borrowReserves: Array<PublicKey> = [];
298
+ if (obligation instanceof KaminoObligation) {
299
+ kaminoObligation = obligation;
300
+ } else {
301
+ const obligationAddress = obligation.toPda(kaminoMarket.getAddress(), owner);
302
+ kaminoObligation = await KaminoObligation.load(kaminoMarket, obligationAddress);
303
+ }
304
+ if (kaminoObligation !== null) {
305
+ depositReserves.push(...[...kaminoObligation.deposits.keys()]);
306
+ borrowReserves.push(...[...kaminoObligation.borrows.keys()]);
307
+ }
308
+
309
+ if (!outflowReserve && action === 'depositAndBorrow') {
310
+ throw new Error(`Outflow reserve has not been set for depositAndBorrow`);
311
+ }
312
+
313
+ // Union of addresses
314
+ const distinctReserveCount =
315
+ new PublicKeySet<PublicKey>([
316
+ ...borrowReserves.map((e) => e),
317
+ ...(action === 'borrow' ? [reserve] : []),
318
+ ...(action === 'depositAndBorrow' ? [reserve] : []),
319
+ ]).toArray().length +
320
+ new PublicKeySet<PublicKey>([
321
+ ...depositReserves.map((e) => e),
322
+ ...(action === 'deposit' ? [reserve] : []),
323
+ ...(action === 'depositAndBorrow' ? [outflowReserve!] : []),
324
+ ]).toArray().length;
325
+
326
+ if (distinctReserveCount > POSITION_LIMIT) {
327
+ throw Error(`Obligation already has max number of positions: ${POSITION_LIMIT}`);
328
+ }
329
+
330
+ return {
331
+ kaminoObligation,
332
+ depositReserves,
333
+ borrowReserves,
334
+ distinctReserveCount,
335
+ };
336
+ }
337
+
338
+ static async buildRefreshObligationTxns(
339
+ kaminoMarket: KaminoMarket,
340
+ payer: PublicKey,
341
+ obligation: KaminoObligation,
342
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
343
+ currentSlot: number = 0
344
+ ) {
345
+ // placeholder for action initialization
346
+ const firstReserve = obligation.state.deposits[0].depositReserve;
347
+ const firstKaminoReserve = kaminoMarket.getReserveByAddress(firstReserve);
348
+ if (!firstKaminoReserve) {
349
+ throw new Error(`Reserve ${firstReserve.toBase58()} not found`);
350
+ }
351
+ const axn = await KaminoAction.initialize(
352
+ 'refreshObligation',
353
+ '0',
354
+ firstKaminoReserve?.getLiquidityMint(),
355
+ obligation.state.owner,
356
+ kaminoMarket,
357
+ obligation,
358
+ undefined,
359
+ currentSlot
360
+ );
361
+
362
+ if (extraComputeBudget > 0) {
363
+ axn.addComputeBudgetIxn(extraComputeBudget);
364
+ }
365
+
366
+ axn.addRefreshObligation(payer);
367
+
368
+ return axn;
369
+ }
370
+
371
+ static async buildRequestElevationGroupTxns(
372
+ kaminoMarket: KaminoMarket,
373
+ payer: PublicKey,
374
+ obligation: KaminoObligation,
375
+ elevationGroup: number,
376
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
377
+ currentSlot: number = 0
378
+ ) {
379
+ const firstReserve = obligation.state.deposits.find(
380
+ (x) => !x.depositReserve.equals(PublicKey.default)
381
+ )!.depositReserve;
382
+ const firstKaminoReserve = kaminoMarket.getReserveByAddress(firstReserve);
383
+ if (!firstKaminoReserve) {
384
+ throw new Error(`Reserve ${firstReserve.toBase58()} not found`);
385
+ }
386
+ const axn = await KaminoAction.initialize(
387
+ 'requestElevationGroup',
388
+ '0',
389
+ firstKaminoReserve?.getLiquidityMint(),
390
+ obligation.state.owner,
391
+ kaminoMarket,
392
+ obligation,
393
+ undefined,
394
+ currentSlot
395
+ );
396
+
397
+ if (extraComputeBudget > 0) {
398
+ axn.addComputeBudgetIxn(extraComputeBudget);
399
+ }
400
+
401
+ axn.addRefreshObligation(payer);
402
+ axn.addRequestElevationIx(elevationGroup, 'setup');
403
+
404
+ return axn;
405
+ }
406
+
407
+ static async buildDepositTxns(
408
+ kaminoMarket: KaminoMarket,
409
+ amount: string | BN,
410
+ mint: PublicKey,
411
+ owner: PublicKey,
412
+ obligation: KaminoObligation | ObligationType,
413
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
414
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
415
+ requestElevationGroup: boolean = false,
416
+ includeUserMetadata: boolean = true, // if true it includes user metadata
417
+ referrer: PublicKey = PublicKey.default,
418
+ currentSlot: number = 0,
419
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' },
420
+ overrideElevationGroupRequest: number | undefined = undefined // if set, when an elevationgroup request is made, it will use this value
421
+ ) {
422
+ const axn = await KaminoAction.initialize(
423
+ 'deposit',
424
+ amount,
425
+ mint,
426
+ owner,
427
+ kaminoMarket,
428
+ obligation,
429
+ referrer,
430
+ currentSlot
431
+ );
432
+ const addInitObligationForFarm = true;
433
+
434
+ if (extraComputeBudget > 0) {
435
+ axn.addComputeBudgetIxn(extraComputeBudget);
436
+ }
437
+
438
+ const allReserves = new PublicKeySet<PublicKey>([
439
+ ...axn.depositReserves,
440
+ ...axn.borrowReserves,
441
+ axn.reserve.address,
442
+ ]).toArray();
443
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
444
+
445
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
446
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
447
+ }
448
+ await axn.addSupportIxs(
449
+ 'deposit',
450
+ includeAtaIxns,
451
+ requestElevationGroup,
452
+ includeUserMetadata,
453
+ addInitObligationForFarm,
454
+ undefined,
455
+ overrideElevationGroupRequest
456
+ );
457
+ axn.addDepositIx();
458
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
459
+
460
+ return axn;
461
+ }
462
+
463
+ getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: PublicKey[]): number[] {
464
+ const tokenIds: number[] = [];
465
+
466
+ for (const reserveAddress of reserves) {
467
+ const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
468
+ if (!reserve) {
469
+ throw new Error(`Reserve not found for reserve ${reserveAddress.toBase58()}`);
470
+ }
471
+
472
+ if (!reserve.state.config.tokenInfo.scopeConfiguration.priceFeed.equals(PublicKey.default)) {
473
+ reserve.state.config.tokenInfo.scopeConfiguration.priceChain.map((x) => {
474
+ if (x !== U16_MAX) {
475
+ tokenIds.push(x);
476
+ }
477
+ });
478
+ reserve.state.config.tokenInfo.scopeConfiguration.twapChain.map((x) => {
479
+ if (x !== U16_MAX) {
480
+ tokenIds.push(x);
481
+ }
482
+ });
483
+ }
484
+ }
485
+
486
+ return tokenIds;
487
+ }
488
+
489
+ async addScopeRefreshIxs(tokens: number[], feed: string = 'hubble') {
490
+ this.preTxnIxsLabels.unshift(`refreshScopePrices`);
491
+ this.preTxnIxs.unshift(
492
+ await this.kaminoMarket.scope.refreshPriceListIx(
493
+ {
494
+ feed: feed,
495
+ },
496
+ tokens
497
+ )
498
+ );
499
+ }
500
+
501
+ static async buildBorrowTxns(
502
+ kaminoMarket: KaminoMarket,
503
+ amount: string | BN,
504
+ mint: PublicKey,
505
+ owner: PublicKey,
506
+ obligation: KaminoObligation | ObligationType,
507
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
508
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
509
+ requestElevationGroup: boolean = false,
510
+ includeUserMetadata: boolean = true, // if true it includes user metadata
511
+ referrer: PublicKey = PublicKey.default,
512
+ currentSlot: number = 0,
513
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' },
514
+ overrideElevationGroupRequest: number | undefined = undefined // if set, when an elevationgroup request is made, it will use this value
515
+ ) {
516
+ const axn = await KaminoAction.initialize(
517
+ 'borrow',
518
+ amount,
519
+ mint,
520
+ owner,
521
+ kaminoMarket,
522
+ obligation,
523
+ referrer,
524
+ currentSlot
525
+ );
526
+ const addInitObligationForFarm = true;
527
+ if (extraComputeBudget > 0) {
528
+ axn.addComputeBudgetIxn(extraComputeBudget);
529
+ }
530
+
531
+ const allReserves = new PublicKeySet<PublicKey>([
532
+ ...axn.depositReserves,
533
+ ...axn.borrowReserves,
534
+ axn.reserve.address,
535
+ ]).toArray();
536
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
537
+
538
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
539
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
540
+ }
541
+
542
+ await axn.addSupportIxs(
543
+ 'borrow',
544
+ includeAtaIxns,
545
+ requestElevationGroup,
546
+ includeUserMetadata,
547
+ addInitObligationForFarm,
548
+ undefined,
549
+ overrideElevationGroupRequest
550
+ );
551
+ axn.addBorrowIx();
552
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
553
+
554
+ return axn;
555
+ }
556
+
557
+ static async buildDepositReserveLiquidityTxns(
558
+ kaminoMarket: KaminoMarket,
559
+ amount: string | BN,
560
+ mint: PublicKey,
561
+ owner: PublicKey,
562
+ obligation: KaminoObligation | ObligationType,
563
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
564
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
565
+ requestElevationGroup: boolean = false,
566
+ includeUserMetadata: boolean = true, // if true it includes user metadata
567
+ referrer: PublicKey = PublicKey.default,
568
+ currentSlot: number = 0,
569
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
570
+ ) {
571
+ const axn = await KaminoAction.initialize(
572
+ 'mint',
573
+ amount,
574
+ mint,
575
+ owner,
576
+ kaminoMarket,
577
+ obligation,
578
+ referrer,
579
+ currentSlot
580
+ );
581
+ const addInitObligationForFarm = true;
582
+
583
+ if (extraComputeBudget > 0) {
584
+ axn.addComputeBudgetIxn(extraComputeBudget);
585
+ }
586
+
587
+ const allReserves = new PublicKeySet<PublicKey>([
588
+ ...axn.depositReserves,
589
+ ...axn.borrowReserves,
590
+ axn.reserve.address,
591
+ ]).toArray();
592
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
593
+
594
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
595
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
596
+ }
597
+
598
+ await axn.addSupportIxs(
599
+ 'mint',
600
+ includeAtaIxns,
601
+ requestElevationGroup,
602
+ includeUserMetadata,
603
+ addInitObligationForFarm
604
+ );
605
+ axn.addDepositReserveLiquidityIx();
606
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
607
+ return axn;
608
+ }
609
+
610
+ static async buildRedeemReserveCollateralTxns(
611
+ kaminoMarket: KaminoMarket,
612
+ amount: string | BN,
613
+ mint: PublicKey,
614
+ owner: PublicKey,
615
+ obligation: KaminoObligation | ObligationType,
616
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
617
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
618
+ requestElevationGroup: boolean = false,
619
+ includeUserMetadata: boolean = true, // if true it includes user metadata,
620
+ referrer: PublicKey = PublicKey.default,
621
+ currentSlot: number = 0,
622
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
623
+ ) {
624
+ const axn = await KaminoAction.initialize(
625
+ 'redeem',
626
+ amount,
627
+ mint,
628
+ owner,
629
+ kaminoMarket,
630
+ obligation,
631
+ referrer,
632
+ currentSlot
633
+ );
634
+ const addInitObligationForFarm = true;
635
+
636
+ if (extraComputeBudget > 0) {
637
+ axn.addComputeBudgetIxn(extraComputeBudget);
638
+ }
639
+
640
+ const allReserves = new PublicKeySet<PublicKey>([
641
+ ...axn.depositReserves,
642
+ ...axn.borrowReserves,
643
+ axn.reserve.address,
644
+ ]).toArray();
645
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
646
+
647
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
648
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
649
+ }
650
+
651
+ await axn.addSupportIxs(
652
+ 'redeem',
653
+ includeAtaIxns,
654
+ requestElevationGroup,
655
+ includeUserMetadata,
656
+ addInitObligationForFarm
657
+ );
658
+ axn.addRedeemReserveCollateralIx();
659
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
660
+ return axn;
661
+ }
662
+
663
+ static async buildDepositObligationCollateralTxns(
664
+ kaminoMarket: KaminoMarket,
665
+ amount: string | BN,
666
+ mint: PublicKey,
667
+ owner: PublicKey,
668
+ obligation: KaminoObligation | ObligationType,
669
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
670
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
671
+ requestElevationGroup: boolean = false,
672
+ includeUserMetadata: boolean = true, // if true it includes user metadata
673
+ referrer: PublicKey = PublicKey.default,
674
+ currentSlot: number = 0,
675
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
676
+ ) {
677
+ const axn = await KaminoAction.initialize(
678
+ 'depositCollateral',
679
+ amount,
680
+ mint,
681
+ owner,
682
+ kaminoMarket,
683
+ obligation,
684
+ referrer,
685
+ currentSlot
686
+ );
687
+ const addInitObligationForFarm = true;
688
+
689
+ if (extraComputeBudget > 0) {
690
+ axn.addComputeBudgetIxn(extraComputeBudget);
691
+ }
692
+
693
+ const allReserves = new PublicKeySet<PublicKey>([
694
+ ...axn.depositReserves,
695
+ ...axn.borrowReserves,
696
+ axn.reserve.address,
697
+ ]).toArray();
698
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
699
+
700
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
701
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
702
+ }
703
+
704
+ await axn.addSupportIxs(
705
+ 'depositCollateral',
706
+ includeAtaIxns,
707
+ requestElevationGroup,
708
+ includeUserMetadata,
709
+ addInitObligationForFarm
710
+ );
711
+ axn.addDepositObligationCollateralIx();
712
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
713
+ return axn;
714
+ }
715
+
716
+ static async buildDepositAndBorrowTxns(
717
+ kaminoMarket: KaminoMarket,
718
+ depositAmount: string | BN,
719
+ depositMint: PublicKey,
720
+ borrowAmount: string | BN,
721
+ borrowMint: PublicKey,
722
+ payer: PublicKey,
723
+ obligation: KaminoObligation | ObligationType,
724
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
725
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
726
+ requestElevationGroup: boolean = false,
727
+ includeUserMetadata: boolean = true, // if true it includes user metadata,
728
+ referrer: PublicKey = PublicKey.default,
729
+ currentSlot: number = 0,
730
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
731
+ ) {
732
+ const axn = await KaminoAction.initializeMultiTokenAction(
733
+ kaminoMarket,
734
+ 'depositAndBorrow',
735
+ depositAmount,
736
+ depositMint,
737
+ borrowMint,
738
+ payer,
739
+ payer,
740
+ obligation,
741
+ borrowAmount,
742
+ referrer,
743
+ currentSlot
744
+ );
745
+ const addInitObligationForFarmForDeposit = true;
746
+ const addInitObligationForFarmForBorrow = false;
747
+ const twoTokenAction = true;
748
+
749
+ if (extraComputeBudget > 0) {
750
+ axn.addComputeBudgetIxn(extraComputeBudget);
751
+ }
752
+
753
+ const allReserves = new PublicKeySet<PublicKey>([
754
+ ...axn.depositReserves,
755
+ ...axn.borrowReserves,
756
+ axn.reserve.address,
757
+ axn.outflowReserve!.address,
758
+ ]).toArray();
759
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
760
+
761
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
762
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
763
+ }
764
+
765
+ await axn.addSupportIxs(
766
+ 'deposit',
767
+ includeAtaIxns,
768
+ requestElevationGroup,
769
+ includeUserMetadata,
770
+ addInitObligationForFarmForDeposit,
771
+ twoTokenAction
772
+ );
773
+ await axn.addDepositAndBorrowIx();
774
+ await axn.addInBetweenIxs(
775
+ 'depositAndBorrow',
776
+ includeAtaIxns,
777
+ requestElevationGroup,
778
+ addInitObligationForFarmForBorrow
779
+ );
780
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
781
+ return axn;
782
+ }
783
+
784
+ static async buildRepayAndWithdrawTxns(
785
+ kaminoMarket: KaminoMarket,
786
+ repayAmount: string | BN,
787
+ repayMint: PublicKey,
788
+ withdrawAmount: string | BN,
789
+ withdrawMint: PublicKey,
790
+ payer: PublicKey,
791
+ currentSlot: number,
792
+ obligation: KaminoObligation | ObligationType,
793
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
794
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
795
+ requestElevationGroup: boolean = false,
796
+ includeUserMetadata: boolean = true, // if true it includes user metadata,
797
+ isClosingPosition: boolean = false,
798
+ referrer: PublicKey = PublicKey.default,
799
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
800
+ ) {
801
+ const axn = await KaminoAction.initializeMultiTokenAction(
802
+ kaminoMarket,
803
+ 'repayAndWithdraw',
804
+ repayAmount,
805
+ repayMint,
806
+ withdrawMint,
807
+ payer,
808
+ payer,
809
+ obligation,
810
+ withdrawAmount,
811
+ referrer,
812
+ currentSlot
813
+ );
814
+ const addInitObligationForFarmForRepay = true;
815
+ const addInitObligationForFarmForWithdraw = false;
816
+ const twoTokenAction = true;
817
+ if (extraComputeBudget > 0) {
818
+ axn.addComputeBudgetIxn(extraComputeBudget);
819
+ }
820
+
821
+ const allReserves = new PublicKeySet<PublicKey>([
822
+ ...axn.depositReserves,
823
+ ...axn.borrowReserves,
824
+ axn.reserve.address,
825
+ axn.outflowReserve!.address,
826
+ ]).toArray();
827
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
828
+
829
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
830
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
831
+ }
832
+
833
+ await axn.addSupportIxs(
834
+ 'repay',
835
+ includeAtaIxns,
836
+ requestElevationGroup,
837
+ includeUserMetadata,
838
+ addInitObligationForFarmForRepay,
839
+ twoTokenAction
840
+ );
841
+ await axn.addRepayAndWithdrawIxs();
842
+ await axn.addInBetweenIxs(
843
+ 'repayAndWithdraw',
844
+ includeAtaIxns,
845
+ requestElevationGroup,
846
+ addInitObligationForFarmForWithdraw,
847
+ isClosingPosition
848
+ );
849
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
850
+ return axn;
851
+ }
852
+
853
+ static async buildWithdrawTxns(
854
+ kaminoMarket: KaminoMarket,
855
+ amount: string | BN,
856
+ mint: PublicKey,
857
+ owner: PublicKey,
858
+ obligation: KaminoObligation | ObligationType,
859
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
860
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
861
+ requestElevationGroup: boolean = false,
862
+ includeUserMetadata: boolean = true, // if true it includes user metadata
863
+ referrer: PublicKey = PublicKey.default,
864
+ currentSlot: number = 0,
865
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
866
+ ) {
867
+ const axn = await KaminoAction.initialize(
868
+ 'withdraw',
869
+ amount,
870
+ mint,
871
+ owner,
872
+ kaminoMarket,
873
+ obligation,
874
+ referrer,
875
+ currentSlot
876
+ );
877
+ const addInitObligationForFarm = true;
878
+
879
+ if (extraComputeBudget > 0) {
880
+ axn.addComputeBudgetIxn(extraComputeBudget);
881
+ }
882
+
883
+ const allReserves = new PublicKeySet<PublicKey>([
884
+ ...axn.depositReserves,
885
+ ...axn.borrowReserves,
886
+ axn.reserve.address,
887
+ ]).toArray();
888
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
889
+
890
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
891
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
892
+ }
893
+
894
+ await axn.addSupportIxs(
895
+ 'withdraw',
896
+ includeAtaIxns,
897
+ requestElevationGroup,
898
+ includeUserMetadata,
899
+ addInitObligationForFarm
900
+ );
901
+ await axn.addWithdrawIx();
902
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
903
+
904
+ return axn;
905
+ }
906
+
907
+ /**
908
+ *
909
+ * @param kaminoMarket
910
+ * @param amount
911
+ * @param mint
912
+ * @param owner
913
+ * @param obligation - obligation to repay or the PDA seeds
914
+ * @param currentSlot
915
+ * @param payer - if not set then owner is used
916
+ * @param extraComputeBudget - if > 0 then adds the ixn
917
+ * @param includeAtaIxns - if true it includes create and close wsol and token atas
918
+ * @param requestElevationGroup
919
+ * @param includeUserMetadata - if true it includes user metadata
920
+ * @param referrer
921
+ */
922
+ static async buildRepayTxns(
923
+ kaminoMarket: KaminoMarket,
924
+ amount: string | BN,
925
+ mint: PublicKey,
926
+ owner: PublicKey,
927
+ obligation: KaminoObligation | ObligationType,
928
+ currentSlot: number,
929
+ payer: PublicKey | undefined = undefined,
930
+ extraComputeBudget: number = 1_000_000,
931
+ includeAtaIxns: boolean = true,
932
+ requestElevationGroup: boolean = false,
933
+ includeUserMetadata: boolean = true,
934
+ referrer: PublicKey = PublicKey.default,
935
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
936
+ ) {
937
+ const axn = await KaminoAction.initialize(
938
+ 'repay',
939
+ amount,
940
+ mint,
941
+ owner,
942
+ kaminoMarket,
943
+ obligation,
944
+ referrer,
945
+ currentSlot,
946
+ payer
947
+ );
948
+ const addInitObligationForFarm = true;
949
+
950
+ if (extraComputeBudget > 0) {
951
+ axn.addComputeBudgetIxn(extraComputeBudget);
952
+ }
953
+
954
+ const allReserves = new PublicKeySet<PublicKey>([
955
+ ...axn.depositReserves,
956
+ ...axn.borrowReserves,
957
+ axn.reserve.address,
958
+ ]).toArray();
959
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
960
+
961
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
962
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
963
+ }
964
+
965
+ await axn.addSupportIxs(
966
+ 'repay',
967
+ includeAtaIxns,
968
+ requestElevationGroup,
969
+ includeUserMetadata,
970
+ addInitObligationForFarm
971
+ );
972
+ await axn.addRepayIx();
973
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
974
+
975
+ return axn;
976
+ }
977
+
978
+ static async buildLiquidateTxns(
979
+ kaminoMarket: KaminoMarket,
980
+ amount: string | BN,
981
+ minCollateralReceiveAmount: string | BN,
982
+ repayTokenMint: PublicKey,
983
+ withdrawTokenMint: PublicKey,
984
+ liquidator: PublicKey,
985
+ obligationOwner: PublicKey,
986
+ obligation: KaminoObligation | ObligationType,
987
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
988
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas, and creates all other token atas if they don't exist
989
+ requestElevationGroup: boolean = false,
990
+ includeUserMetadata: boolean = true, // if true it includes user metadata
991
+ referrer: PublicKey = PublicKey.default,
992
+ maxAllowedLtvOverridePercent: number = 0,
993
+ currentSlot: number = 0,
994
+ scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
995
+ ) {
996
+ const axn = await KaminoAction.initializeMultiTokenAction(
997
+ kaminoMarket,
998
+ 'liquidate',
999
+ amount,
1000
+ repayTokenMint,
1001
+ withdrawTokenMint,
1002
+ liquidator,
1003
+ obligationOwner,
1004
+ obligation,
1005
+ minCollateralReceiveAmount,
1006
+ referrer,
1007
+ currentSlot
1008
+ );
1009
+ const addInitObligationForFarm = true;
1010
+
1011
+ if (extraComputeBudget > 0) {
1012
+ axn.addComputeBudgetIxn(extraComputeBudget);
1013
+ }
1014
+
1015
+ const allReserves = new PublicKeySet<PublicKey>([
1016
+ ...axn.depositReserves,
1017
+ ...axn.borrowReserves,
1018
+ axn.reserve.address,
1019
+ axn.outflowReserve!.address,
1020
+ ]).toArray();
1021
+ const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
1022
+
1023
+ if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
1024
+ await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
1025
+ }
1026
+
1027
+ await axn.addSupportIxs(
1028
+ 'liquidate',
1029
+ includeAtaIxns,
1030
+ requestElevationGroup,
1031
+ includeUserMetadata,
1032
+ addInitObligationForFarm
1033
+ );
1034
+ await axn.addLiquidateIx(maxAllowedLtvOverridePercent);
1035
+ axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
1036
+
1037
+ return axn;
1038
+ }
1039
+
1040
+ static async buildWithdrawReferrerFeeTxns(
1041
+ owner: PublicKey,
1042
+ tokenMint: PublicKey,
1043
+ kaminoMarket: KaminoMarket,
1044
+ currentSlot: number = 0
1045
+ ) {
1046
+ const { axn, createAtasIxns } = await KaminoAction.initializeWithdrawReferrerFees(
1047
+ tokenMint,
1048
+ owner,
1049
+ kaminoMarket,
1050
+ currentSlot
1051
+ );
1052
+
1053
+ axn.preTxnIxs.push(...createAtasIxns);
1054
+ axn.preTxnIxsLabels.push(`createAtasIxs[${axn.userTokenAccountAddress.toString()}]`);
1055
+
1056
+ axn.addRefreshReserveIxs([axn.reserve.address]);
1057
+ axn.addWithdrawReferrerFeesIxs();
1058
+
1059
+ return axn;
1060
+ }
1061
+
1062
+ async getTransactions() {
1063
+ const txns: {
1064
+ preLendingTxn: Transaction | null;
1065
+ lendingTxn: Transaction | null;
1066
+ postLendingTxn: Transaction | null;
1067
+ } = {
1068
+ preLendingTxn: null,
1069
+ lendingTxn: null,
1070
+ postLendingTxn: null,
1071
+ };
1072
+
1073
+ if (this.preTxnIxs.length) {
1074
+ txns.preLendingTxn = new Transaction({
1075
+ feePayer: this.owner,
1076
+ recentBlockhash: (await this.kaminoMarket.getConnection().getLatestBlockhash()).blockhash,
1077
+ }).add(...this.preTxnIxs);
1078
+ }
1079
+
1080
+ if (this.lendingIxs.length === 2) {
1081
+ txns.lendingTxn = new Transaction({
1082
+ feePayer: this.owner,
1083
+ recentBlockhash: (await this.kaminoMarket.getConnection().getLatestBlockhash()).blockhash,
1084
+ }).add(
1085
+ ...this.setupIxs,
1086
+ ...[this.lendingIxs[0]],
1087
+ ...this.inBetweenIxs,
1088
+ ...[this.lendingIxs[1]],
1089
+ ...this.cleanupIxs
1090
+ );
1091
+ } else {
1092
+ txns.lendingTxn = new Transaction({
1093
+ feePayer: this.owner,
1094
+ recentBlockhash: (await this.kaminoMarket.getConnection().getLatestBlockhash()).blockhash,
1095
+ }).add(...this.setupIxs, ...this.lendingIxs, ...this.cleanupIxs);
1096
+ }
1097
+
1098
+ if (this.postTxnIxs.length) {
1099
+ txns.postLendingTxn = new Transaction({
1100
+ feePayer: this.owner,
1101
+ recentBlockhash: (await this.kaminoMarket.getConnection().getLatestBlockhash()).blockhash,
1102
+ }).add(...this.postTxnIxs);
1103
+ }
1104
+
1105
+ return txns;
1106
+ }
1107
+
1108
+ async sendTransactions(sendTransaction: (txn: Transaction, connection: Connection) => Promise<TransactionSignature>) {
1109
+ const txns = await this.getTransactions();
1110
+
1111
+ await this.sendSingleTransaction(txns.preLendingTxn, sendTransaction);
1112
+
1113
+ const signature = await this.sendSingleTransaction(txns.lendingTxn, sendTransaction);
1114
+
1115
+ await this.sendSingleTransaction(txns.postLendingTxn, sendTransaction);
1116
+
1117
+ return signature;
1118
+ }
1119
+
1120
+ private async sendSingleTransaction(
1121
+ txn: Transaction | null,
1122
+ sendTransaction: (txn: Transaction, connection: Connection) => Promise<TransactionSignature>
1123
+ ) {
1124
+ if (!txn) return '';
1125
+
1126
+ const signature = await sendTransaction(txn, this.kaminoMarket.getConnection());
1127
+ await this.kaminoMarket.getConnection().confirmTransaction(signature);
1128
+
1129
+ return signature;
1130
+ }
1131
+
1132
+ async simulateTransactions(
1133
+ sendTransaction: (
1134
+ txn: Transaction,
1135
+ connection: Connection
1136
+ ) => Promise<RpcResponseAndContext<SimulatedTransactionResponse>>
1137
+ ) {
1138
+ const txns = await this.getTransactions();
1139
+
1140
+ await this.simulateSingleTransaction(txns.preLendingTxn, sendTransaction);
1141
+
1142
+ const signature = await this.simulateSingleTransaction(txns.lendingTxn, sendTransaction);
1143
+
1144
+ await this.simulateSingleTransaction(txns.postLendingTxn, sendTransaction);
1145
+
1146
+ return signature;
1147
+ }
1148
+
1149
+ private async simulateSingleTransaction(
1150
+ txn: Transaction | null,
1151
+ sendTransaction: (
1152
+ txn: Transaction,
1153
+ connection: Connection
1154
+ ) => Promise<RpcResponseAndContext<SimulatedTransactionResponse>>
1155
+ ) {
1156
+ if (!txn) return '';
1157
+ return await sendTransaction(txn, this.kaminoMarket.getConnection());
1158
+ }
1159
+
1160
+ addDepositIx() {
1161
+ this.lendingIxsLabels.push(`depositReserveLiquidityAndObligationCollateral`);
1162
+ this.lendingIxs.push(
1163
+ depositReserveLiquidityAndObligationCollateral(
1164
+ {
1165
+ liquidityAmount: this.amount,
1166
+ },
1167
+ {
1168
+ owner: this.owner,
1169
+ obligation: this.getObligationPda(),
1170
+ lendingMarket: this.kaminoMarket.getAddress(),
1171
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1172
+ reserve: this.reserve.address,
1173
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1174
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1175
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1176
+ reserveDestinationDepositCollateral: this.reserve.state.collateral.supplyVault, // destinationCollateral
1177
+ userSourceLiquidity: this.userTokenAccountAddress,
1178
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1179
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1180
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1181
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1182
+ },
1183
+ this.kaminoMarket.programId
1184
+ )
1185
+ );
1186
+ }
1187
+
1188
+ addDepositReserveLiquidityIx() {
1189
+ this.lendingIxsLabels.push(`depositReserveLiquidity`);
1190
+ this.lendingIxs.push(
1191
+ depositReserveLiquidity(
1192
+ {
1193
+ liquidityAmount: this.amount,
1194
+ },
1195
+ {
1196
+ owner: this.owner,
1197
+ lendingMarket: this.kaminoMarket.getAddress(),
1198
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1199
+ reserve: this.reserve.address,
1200
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1201
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1202
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1203
+ userSourceLiquidity: this.userTokenAccountAddress,
1204
+ userDestinationCollateral: this.userCollateralAccountAddress,
1205
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1206
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1207
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1208
+ },
1209
+ this.kaminoMarket.programId
1210
+ )
1211
+ );
1212
+ }
1213
+
1214
+ addRedeemReserveCollateralIx() {
1215
+ this.lendingIxsLabels.push(`redeemReserveCollateral`);
1216
+ this.lendingIxs.push(
1217
+ redeemReserveCollateral(
1218
+ {
1219
+ collateralAmount: this.amount,
1220
+ },
1221
+ {
1222
+ owner: this.owner,
1223
+ lendingMarket: this.kaminoMarket.getAddress(),
1224
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1225
+ reserve: this.reserve.address,
1226
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1227
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1228
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1229
+ userSourceCollateral: this.userCollateralAccountAddress,
1230
+ userDestinationLiquidity: this.userTokenAccountAddress,
1231
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1232
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1233
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1234
+ },
1235
+ this.kaminoMarket.programId
1236
+ )
1237
+ );
1238
+ }
1239
+
1240
+ addDepositObligationCollateralIx() {
1241
+ this.lendingIxsLabels.push(`depositObligationCollateral`);
1242
+ this.lendingIxs.push(
1243
+ depositObligationCollateral(
1244
+ {
1245
+ collateralAmount: this.amount,
1246
+ },
1247
+ {
1248
+ owner: this.owner,
1249
+ obligation: this.getObligationPda(),
1250
+ lendingMarket: this.kaminoMarket.getAddress(),
1251
+ depositReserve: this.reserve.address,
1252
+ reserveDestinationCollateral: this.reserve.state.collateral.supplyVault,
1253
+ userSourceCollateral: this.userCollateralAccountAddress,
1254
+ tokenProgram: TOKEN_PROGRAM_ID,
1255
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1256
+ },
1257
+ this.kaminoMarket.programId
1258
+ )
1259
+ );
1260
+ }
1261
+
1262
+ addBorrowIx() {
1263
+ this.lendingIxsLabels.push(`borrowObligationLiquidity`);
1264
+
1265
+ const depositReservesList = this.getAdditionalDepositReservesList();
1266
+
1267
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1268
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1269
+ });
1270
+
1271
+ const borrowIx = borrowObligationLiquidity(
1272
+ {
1273
+ liquidityAmount: this.amount,
1274
+ },
1275
+ {
1276
+ owner: this.owner,
1277
+ obligation: this.getObligationPda(),
1278
+ lendingMarket: this.kaminoMarket.getAddress(),
1279
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1280
+ borrowReserve: this.reserve.address,
1281
+ borrowReserveLiquidityMint: this.reserve.getLiquidityMint(),
1282
+ reserveSourceLiquidity: this.reserve.state.liquidity.supplyVault,
1283
+ userDestinationLiquidity: this.userTokenAccountAddress,
1284
+ borrowReserveLiquidityFeeReceiver: this.reserve.state.liquidity.feeVault,
1285
+ referrerTokenState: referrerTokenStatePda(this.referrer, this.reserve.address, this.kaminoMarket.programId)[0],
1286
+ tokenProgram: this.reserve.getLiquidityTokenProgram(),
1287
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1288
+ },
1289
+ this.kaminoMarket.programId
1290
+ );
1291
+ borrowIx.keys =
1292
+ this.obligation!.state.elevationGroup > 0 || this.obligation!.refreshedStats.potentialElevationGroupUpdate > 0
1293
+ ? borrowIx.keys.concat([...depositReserveAccountMetas])
1294
+ : borrowIx.keys;
1295
+ this.lendingIxs.push(borrowIx);
1296
+ }
1297
+
1298
+ async addDepositAndBorrowIx() {
1299
+ this.lendingIxsLabels.push(`depositReserveLiquidityAndObligationCollateral`);
1300
+ this.lendingIxsLabels.push(`borrowObligationLiquidity`);
1301
+ this.lendingIxs.push(
1302
+ depositReserveLiquidityAndObligationCollateral(
1303
+ {
1304
+ liquidityAmount: this.amount,
1305
+ },
1306
+ {
1307
+ owner: this.owner,
1308
+ obligation: this.getObligationPda(),
1309
+ lendingMarket: this.kaminoMarket.getAddress(),
1310
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1311
+ reserve: this.reserve.address,
1312
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1313
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1314
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1315
+ reserveDestinationDepositCollateral: this.reserve.state.collateral.supplyVault, // destinationCollateral
1316
+ userSourceLiquidity: this.userTokenAccountAddress,
1317
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1318
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1319
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1320
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1321
+ },
1322
+ this.kaminoMarket.programId
1323
+ )
1324
+ );
1325
+
1326
+ if (!this.outflowReserve) {
1327
+ throw new Error(`outflowReserve not set`);
1328
+ }
1329
+
1330
+ if (!this.additionalTokenAccountAddress) {
1331
+ throw new Error(`additionalTokenAccountAddress not set`);
1332
+ }
1333
+
1334
+ if (!this.outflowAmount) {
1335
+ throw new Error(`outflowAmount not set`);
1336
+ }
1337
+
1338
+ const depositReservesList = this.getAdditionalDepositReservesList();
1339
+ if (depositReservesList.length === 0) {
1340
+ depositReservesList.push(this.reserve.address);
1341
+ }
1342
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1343
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1344
+ });
1345
+
1346
+ const borrowIx = borrowObligationLiquidity(
1347
+ {
1348
+ liquidityAmount: this.outflowAmount,
1349
+ },
1350
+ {
1351
+ owner: this.owner,
1352
+ obligation: this.getObligationPda(),
1353
+ lendingMarket: this.kaminoMarket.getAddress(),
1354
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1355
+ borrowReserve: this.outflowReserve.address,
1356
+ borrowReserveLiquidityMint: this.outflowReserve.getLiquidityMint(),
1357
+ reserveSourceLiquidity: this.outflowReserve.state.liquidity.supplyVault,
1358
+ userDestinationLiquidity: this.additionalTokenAccountAddress,
1359
+ borrowReserveLiquidityFeeReceiver: this.outflowReserve.state.liquidity.feeVault,
1360
+ referrerTokenState: referrerTokenStatePda(
1361
+ this.referrer,
1362
+ this.outflowReserve.address,
1363
+ this.kaminoMarket.programId
1364
+ )[0],
1365
+ tokenProgram: this.outflowReserve.getLiquidityTokenProgram(),
1366
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1367
+ },
1368
+ this.kaminoMarket.programId
1369
+ );
1370
+
1371
+ borrowIx.keys = borrowIx.keys.concat([...depositReserveAccountMetas]);
1372
+
1373
+ this.lendingIxs.push(borrowIx);
1374
+ }
1375
+
1376
+ async addRepayAndWithdrawIxs() {
1377
+ this.lendingIxsLabels.push(
1378
+ `repayObligationLiquidity(reserve=${this.reserve!.address})(obligation=${this.getObligationPda()})`
1379
+ );
1380
+ this.lendingIxsLabels.push(`withdrawObligationCollateralAndRedeemReserveCollateral`);
1381
+
1382
+ const depositReservesList = this.getAdditionalDepositReservesList();
1383
+
1384
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1385
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1386
+ });
1387
+ const repayIx = repayObligationLiquidity(
1388
+ {
1389
+ liquidityAmount: this.amount,
1390
+ },
1391
+ {
1392
+ owner: this.owner,
1393
+ obligation: this.getObligationPda(),
1394
+ lendingMarket: this.kaminoMarket.getAddress(),
1395
+ repayReserve: this.reserve!.address,
1396
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1397
+ userSourceLiquidity: this.userTokenAccountAddress,
1398
+ reserveDestinationLiquidity: this.reserve.state.liquidity.supplyVault,
1399
+ tokenProgram: this.reserve.getLiquidityTokenProgram(),
1400
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1401
+ },
1402
+ this.kaminoMarket.programId
1403
+ );
1404
+
1405
+ repayIx.keys = repayIx.keys.concat([...depositReserveAccountMetas]);
1406
+
1407
+ this.lendingIxs.push(repayIx);
1408
+ if (!this.outflowReserve) {
1409
+ throw new Error(`outflowReserve not set`);
1410
+ }
1411
+
1412
+ if (!this.additionalTokenAccountAddress) {
1413
+ throw new Error(`additionalTokenAccountAddress not set`);
1414
+ }
1415
+
1416
+ if (!this.outflowAmount) {
1417
+ throw new Error(`outflowAmount not set`);
1418
+ }
1419
+
1420
+ const collateralExchangeRate = this.outflowReserve.getEstimatedCollateralExchangeRate(
1421
+ this.currentSlot,
1422
+ this.kaminoMarket.state.referralFeeBps
1423
+ );
1424
+
1425
+ this.lendingIxs.push(
1426
+ withdrawObligationCollateralAndRedeemReserveCollateral(
1427
+ {
1428
+ collateralAmount: this.outflowAmount.eq(new BN(U64_MAX))
1429
+ ? this.outflowAmount
1430
+ : new BN(new Decimal(this.outflowAmount.toString()).mul(collateralExchangeRate).ceil().toString()),
1431
+ },
1432
+ {
1433
+ owner: this.owner,
1434
+ obligation: this.getObligationPda(),
1435
+ lendingMarket: this.kaminoMarket.getAddress(),
1436
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1437
+ withdrawReserve: this.outflowReserve.address,
1438
+ reserveLiquidityMint: this.outflowReserve.getLiquidityMint(),
1439
+ reserveCollateralMint: this.outflowReserve.getCTokenMint(),
1440
+ reserveLiquiditySupply: this.outflowReserve.state.liquidity.supplyVault,
1441
+ reserveSourceCollateral: this.outflowReserve.state.collateral.supplyVault,
1442
+ userDestinationLiquidity: this.additionalTokenAccountAddress,
1443
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1444
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1445
+ liquidityTokenProgram: this.outflowReserve.getLiquidityTokenProgram(),
1446
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1447
+ },
1448
+ this.kaminoMarket.programId
1449
+ )
1450
+ );
1451
+ }
1452
+
1453
+ async addWithdrawIx() {
1454
+ const collateralExchangeRate = this.reserve.getEstimatedCollateralExchangeRate(
1455
+ this.currentSlot,
1456
+ this.kaminoMarket.state.referralFeeBps
1457
+ );
1458
+
1459
+ const collateralAmount = this.amount.eq(new BN(U64_MAX))
1460
+ ? this.amount
1461
+ : new BN(new Decimal(this.amount.toString()).mul(collateralExchangeRate).ceil().toString());
1462
+
1463
+ this.lendingIxsLabels.push(`withdrawObligationCollateralAndRedeemReserveCollateral`);
1464
+ this.lendingIxs.push(
1465
+ withdrawObligationCollateralAndRedeemReserveCollateral(
1466
+ {
1467
+ collateralAmount,
1468
+ },
1469
+ {
1470
+ owner: this.owner,
1471
+ obligation: this.getObligationPda(),
1472
+ lendingMarket: this.kaminoMarket.getAddress(),
1473
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1474
+ withdrawReserve: this.reserve.address,
1475
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1476
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1477
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1478
+ reserveSourceCollateral: this.reserve.state.collateral.supplyVault,
1479
+ userDestinationLiquidity: this.userTokenAccountAddress,
1480
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1481
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1482
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1483
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1484
+ },
1485
+ this.kaminoMarket.programId
1486
+ )
1487
+ );
1488
+ }
1489
+
1490
+ async addRepayIx() {
1491
+ this.lendingIxsLabels.push(
1492
+ `repayObligationLiquidity(reserve=${this.reserve.address})(obligation=${this.getObligationPda()})`
1493
+ );
1494
+
1495
+ const depositReservesList = this.getAdditionalDepositReservesList();
1496
+
1497
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1498
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1499
+ });
1500
+
1501
+ const repayIx = repayObligationLiquidity(
1502
+ {
1503
+ liquidityAmount: this.amount,
1504
+ },
1505
+ {
1506
+ owner: this.payer,
1507
+ obligation: this.getObligationPda(),
1508
+ lendingMarket: this.kaminoMarket.getAddress(),
1509
+ repayReserve: this.reserve.address,
1510
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1511
+ userSourceLiquidity: this.userTokenAccountAddress,
1512
+ reserveDestinationLiquidity: this.reserve.state.liquidity.supplyVault,
1513
+ tokenProgram: this.reserve.getLiquidityTokenProgram(),
1514
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1515
+ },
1516
+ this.kaminoMarket.programId
1517
+ );
1518
+
1519
+ repayIx.keys =
1520
+ this.obligation!.state.elevationGroup > 0 ? repayIx.keys.concat([...depositReserveAccountMetas]) : repayIx.keys;
1521
+
1522
+ this.lendingIxs.push(repayIx);
1523
+ }
1524
+
1525
+ async addLiquidateIx(maxAllowedLtvOverridePercent: number = 0) {
1526
+ this.lendingIxsLabels.push(`liquidateObligationAndRedeemReserveCollateral`);
1527
+ if (!this.outflowReserve) {
1528
+ throw Error(`Withdraw reserve during liquidation is not defined`);
1529
+ }
1530
+ if (!this.additionalTokenAccountAddress) {
1531
+ throw Error(`Liquidating token account address is not defined`);
1532
+ }
1533
+
1534
+ const depositReservesList = this.getAdditionalDepositReservesList();
1535
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1536
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1537
+ });
1538
+
1539
+ const liquidateIx = liquidateObligationAndRedeemReserveCollateral(
1540
+ {
1541
+ liquidityAmount: this.amount,
1542
+ // TODO: Configure this when updating liquidator with new interface
1543
+ minAcceptableReceivedLiquidityAmount: this.outflowAmount || new BN(0),
1544
+ maxAllowedLtvOverridePercent: new BN(maxAllowedLtvOverridePercent),
1545
+ },
1546
+ {
1547
+ liquidator: this.owner,
1548
+ obligation: this.getObligationPda(),
1549
+ lendingMarket: this.kaminoMarket.getAddress(),
1550
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1551
+ repayReserve: this.reserve.address,
1552
+ repayReserveLiquidityMint: this.reserve.getLiquidityMint(),
1553
+ repayReserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1554
+ withdrawReserve: this.outflowReserve.address,
1555
+ withdrawReserveLiquidityMint: this.outflowReserve.getLiquidityMint(),
1556
+ withdrawReserveCollateralMint: this.outflowReserve.getCTokenMint(),
1557
+ withdrawReserveCollateralSupply: this.outflowReserve.state.collateral.supplyVault,
1558
+ withdrawReserveLiquiditySupply: this.outflowReserve.state.liquidity.supplyVault,
1559
+ userSourceLiquidity: this.additionalTokenAccountAddress,
1560
+ userDestinationCollateral: this.userCollateralAccountAddress,
1561
+ userDestinationLiquidity: this.userTokenAccountAddress,
1562
+ withdrawReserveLiquidityFeeReceiver: this.outflowReserve.state.liquidity.feeVault,
1563
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1564
+ repayLiquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1565
+ withdrawLiquidityTokenProgram: this.outflowReserve.getLiquidityTokenProgram(),
1566
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1567
+ },
1568
+ this.kaminoMarket.programId
1569
+ );
1570
+ liquidateIx.keys =
1571
+ this.obligation!.state.elevationGroup > 0
1572
+ ? liquidateIx.keys.concat([...depositReserveAccountMetas])
1573
+ : liquidateIx.keys;
1574
+ this.lendingIxs.push(liquidateIx);
1575
+ }
1576
+
1577
+ async addInBetweenIxs(
1578
+ action: ActionType,
1579
+ includeAtaIxns: boolean,
1580
+ requestElevationGroup: boolean,
1581
+ addInitObligationForFarm: boolean,
1582
+ isClosingPosition: boolean = false
1583
+ ) {
1584
+ await this.addSupportIxsWithoutInitObligation(
1585
+ action,
1586
+ includeAtaIxns,
1587
+ 'inBetween',
1588
+ requestElevationGroup,
1589
+ addInitObligationForFarm,
1590
+ isClosingPosition
1591
+ );
1592
+ }
1593
+
1594
+ addRefreshObligation(crank: PublicKey) {
1595
+ const uniqueReserveAddresses = new PublicKeySet(this.depositReserves.concat(this.borrowReserves)).toArray();
1596
+
1597
+ const addAllToSetupIxns = 'setup';
1598
+ // Union of addresses
1599
+ const allReservesExcludingCurrent = [...uniqueReserveAddresses];
1600
+
1601
+ this.addRefreshReserveIxs(allReservesExcludingCurrent, addAllToSetupIxns);
1602
+ this.addRefreshFarmsForReserve(
1603
+ this.depositReserves.map((r) => this.kaminoMarket.getReserveByAddress(r)!),
1604
+ addAllToSetupIxns,
1605
+ ReserveFarmKind.Collateral,
1606
+ crank
1607
+ );
1608
+ this.addRefreshFarmsForReserve(
1609
+ this.borrowReserves.map((r) => this.kaminoMarket.getReserveByAddress(r)!),
1610
+ addAllToSetupIxns,
1611
+ ReserveFarmKind.Debt,
1612
+ crank
1613
+ );
1614
+ this.addRefreshObligationIx(addAllToSetupIxns, false);
1615
+ }
1616
+
1617
+ async addSupportIxsWithoutInitObligation(
1618
+ action: ActionType,
1619
+ includeAtaIxns: boolean,
1620
+ addAsSupportIx: AuxiliaryIx = 'setup',
1621
+ requestElevationGroup: boolean = false,
1622
+ addInitObligationForFarm: boolean = false,
1623
+ isClosingPosition: boolean = false,
1624
+ twoTokenAction: boolean = false,
1625
+ overrideElevationGroupRequest?: number
1626
+ ) {
1627
+ // TODO: why are we not doing this first?
1628
+ if (includeAtaIxns) {
1629
+ await this.addAtaIxs(action);
1630
+ }
1631
+
1632
+ if (
1633
+ [
1634
+ 'depositCollateral',
1635
+ 'deposit',
1636
+ 'withdraw',
1637
+ 'borrow',
1638
+ 'liquidate',
1639
+ 'repay',
1640
+ 'depositAndBorrow',
1641
+ 'repayAndWithdraw',
1642
+ 'refreshObligation',
1643
+ ].includes(action)
1644
+ ) {
1645
+ // The support ixns in order are:
1646
+ // 0. Init obligation ixn
1647
+ // 0. Token Ata ixns
1648
+ // 0. Init obligation for farm
1649
+ // 1. Ixns to refresh the reserves of the obligation not related to the current action
1650
+ // 2. Ixn to refresh the reserve of the current action
1651
+ // 3. Ixn to refresh the obligation
1652
+ // 4. Ixn to refresh the `debt` farm of the obligation
1653
+ // 5. Ixn to refresh the `collateral` farm of the obligation
1654
+ // 6. The instruction itself
1655
+ // 7. Ixn to refresh the `debt` farm of the obligation
1656
+ // 8. Ixn to refresh the `collateral` farm of the obligation
1657
+
1658
+ let currentReserves: KaminoReserve[] = [];
1659
+
1660
+ if (action === 'liquidate' || action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
1661
+ if (!this.outflowReserve) {
1662
+ throw new Error('outflowReserve is undefined');
1663
+ }
1664
+
1665
+ if (action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
1666
+ currentReserves = [this.reserve, this.outflowReserve];
1667
+ if (this.obligation) {
1668
+ if (action === 'depositAndBorrow') {
1669
+ const deposit = this.obligation.state.deposits.find((deposit) =>
1670
+ deposit.depositReserve.equals(this.reserve.address)
1671
+ );
1672
+
1673
+ if (!deposit) {
1674
+ this.preLoadedDepositReservesSameTx.push(this.reserve.address);
1675
+ }
1676
+ } else {
1677
+ const borrow = this.obligation.state.borrows.find((borrow) =>
1678
+ borrow.borrowReserve.equals(this.reserve.address)
1679
+ );
1680
+
1681
+ if (!borrow) {
1682
+ throw Error(`Unable to find obligation borrow to repay for ${this.obligation.state.owner.toBase58()}`);
1683
+ }
1684
+
1685
+ const cumulativeBorrowRateObligation = KaminoObligation.getCumulativeBorrowRate(borrow);
1686
+
1687
+ const cumulativeBorrowRateReserve = this.reserve.getEstimatedCumulativeBorrowRate(
1688
+ this.currentSlot,
1689
+ this.kaminoMarket.state.referralFeeBps
1690
+ );
1691
+ const fullRepay = KaminoObligation.getBorrowAmount(borrow)
1692
+ .mul(cumulativeBorrowRateReserve)
1693
+ .div(cumulativeBorrowRateObligation);
1694
+
1695
+ const amountDecimal = new Decimal(this.amount.toString());
1696
+
1697
+ if (fullRepay.lte(amountDecimal)) {
1698
+ this.preLoadedBorrowReservesSameTx.push(this.reserve.address);
1699
+ }
1700
+ }
1701
+ } else {
1702
+ // Obligation doesn't exist yet, so we have to preload the deposit reserve
1703
+ this.preLoadedDepositReservesSameTx.push(this.reserve.address);
1704
+ }
1705
+ } else if (action === 'liquidate' && !this.outflowReserve.address.equals(this.reserve.address)) {
1706
+ currentReserves = [this.outflowReserve, this.reserve];
1707
+ } else {
1708
+ currentReserves = [this.reserve];
1709
+ }
1710
+ } else {
1711
+ currentReserves = [this.reserve];
1712
+ }
1713
+
1714
+ const uniqueReserveAddresses = new PublicKeySet(this.depositReserves.concat(this.borrowReserves));
1715
+ const currentReserveAddresses = new PublicKeySet(currentReserves.map((reserve) => reserve.address));
1716
+
1717
+ // Union of addresses
1718
+ const allReservesExcludingCurrent = [...uniqueReserveAddresses.toArray()].filter(
1719
+ (address) => !currentReserveAddresses.contains(address)
1720
+ );
1721
+
1722
+ this.addRefreshReserveIxs(allReservesExcludingCurrent, addAsSupportIx);
1723
+ if (addInitObligationForFarm) {
1724
+ if (action === 'liquidate') {
1725
+ await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Debt, addAsSupportIx);
1726
+ await this.addInitObligationForFarm(this.outflowReserve!, ReserveFarmKind.Collateral, addAsSupportIx);
1727
+ } else if (
1728
+ action === 'depositAndBorrow' ||
1729
+ action === 'depositCollateral' ||
1730
+ action === 'withdraw' ||
1731
+ action === 'deposit'
1732
+ ) {
1733
+ await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Collateral, addAsSupportIx);
1734
+ if (this.outflowReserve) {
1735
+ await this.addInitObligationForFarm(this.outflowReserve, ReserveFarmKind.Debt, addAsSupportIx);
1736
+ }
1737
+ } else if (action === 'repayAndWithdraw' || action === 'borrow' || action === 'repay') {
1738
+ // todo - probably don't need to add both debt and collateral for everything here
1739
+ await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Debt, addAsSupportIx);
1740
+ if (this.outflowReserve) {
1741
+ await this.addInitObligationForFarm(this.outflowReserve, ReserveFarmKind.Collateral, addAsSupportIx);
1742
+ }
1743
+ } else {
1744
+ await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Collateral, addAsSupportIx);
1745
+ await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Debt, addAsSupportIx);
1746
+ if (this.outflowReserve) {
1747
+ await this.addInitObligationForFarm(this.outflowReserve, ReserveFarmKind.Collateral, addAsSupportIx);
1748
+ await this.addInitObligationForFarm(this.outflowReserve, ReserveFarmKind.Debt, addAsSupportIx);
1749
+ }
1750
+ }
1751
+ }
1752
+ this.addRefreshReserveIxs(currentReserveAddresses.toArray(), addAsSupportIx);
1753
+
1754
+ if (action === 'repayAndWithdraw' && addAsSupportIx === 'inBetween' && isClosingPosition) {
1755
+ // addToSetupIxs === addInBetween (same thing)
1756
+ // If this is a repay and withdraw, and it's not the first action, and it's closing a position
1757
+ // we don't need to include the repay reserve in the refresh obligation
1758
+ // I am ashamed of this code, we need to rewrite this entire thing
1759
+ this.addRefreshObligationIx(addAsSupportIx, true);
1760
+ } else {
1761
+ this.addRefreshObligationIx(addAsSupportIx, false);
1762
+ }
1763
+
1764
+ if (requestElevationGroup) {
1765
+ if (action === 'repay') {
1766
+ const repayObligationLiquidity = this.obligation!.borrows.get(this.reserve.address);
1767
+
1768
+ if (!repayObligationLiquidity) {
1769
+ throw new Error(`Could not find debt reserve ${this.reserve.address} in obligation`);
1770
+ }
1771
+
1772
+ if (
1773
+ new Decimal(repayObligationLiquidity.amount).lte(new Decimal(this.amount.toString())) &&
1774
+ this.obligation!.borrows.size === 1 &&
1775
+ this.obligation?.state.elevationGroup !== 0
1776
+ ) {
1777
+ this.addRefreshReserveIxs(allReservesExcludingCurrent, 'cleanup');
1778
+ // Skip the borrow reserve, since we repay in the same tx
1779
+ this.addRefreshObligationIx('cleanup', true);
1780
+ this.addRequestElevationIx(overrideElevationGroupRequest ?? 0, 'cleanup', true);
1781
+ }
1782
+ } else if (action === 'depositAndBorrow' || action === 'borrow') {
1783
+ let newElevationGroup: number = -1;
1784
+ let addAsSupportIx: AuxiliaryIx = 'setup';
1785
+
1786
+ if (overrideElevationGroupRequest !== undefined) {
1787
+ newElevationGroup = overrideElevationGroupRequest;
1788
+ } else {
1789
+ let emodeGroupsDebt = this.reserve.state.config.elevationGroups;
1790
+ let emodeGroupsColl = this.reserve.state.config.elevationGroups;
1791
+ let debtReserve = this.reserve.address;
1792
+
1793
+ if (action === 'depositAndBorrow') {
1794
+ emodeGroupsDebt = this.outflowReserve!.state.config.elevationGroups;
1795
+ debtReserve = this.outflowReserve!.address;
1796
+ addAsSupportIx = 'inBetween';
1797
+ } else if (action === 'borrow') {
1798
+ const depositReserve = this.obligation!.state.deposits.find(
1799
+ (x) => !x.depositReserve.equals(PublicKey.default)
1800
+ )!.depositReserve;
1801
+ const collReserve = this.kaminoMarket.getReserveByAddress(depositReserve);
1802
+ emodeGroupsColl = collReserve!.state.config.elevationGroups;
1803
+ addAsSupportIx = 'setup';
1804
+ }
1805
+
1806
+ const groups = this.kaminoMarket.state.elevationGroups;
1807
+ const commonElevationGroups = [...emodeGroupsColl].filter(
1808
+ (item) => emodeGroupsDebt.includes(item) && item !== 0 && groups[item - 1].debtReserve.equals(debtReserve)
1809
+ );
1810
+
1811
+ console.log(
1812
+ 'Groups of coll reserve',
1813
+ emodeGroupsColl,
1814
+ 'Groups of debt reserve',
1815
+ emodeGroupsDebt,
1816
+ 'Common groups',
1817
+ commonElevationGroups
1818
+ );
1819
+
1820
+ if (commonElevationGroups.length === 0) {
1821
+ console.log('No common elevation groups found, staying with default');
1822
+ } else {
1823
+ const eModeGroupWithMaxLtvAndDebtReserve = commonElevationGroups.reduce((prev, curr) => {
1824
+ const prevGroup = groups.find((group) => group.id === prev);
1825
+ const currGroup = groups.find((group) => group.id === curr);
1826
+ return prevGroup!.ltvPct > currGroup!.ltvPct ? prev : curr;
1827
+ });
1828
+
1829
+ const eModeGroup = groups.find((group) => group.id === eModeGroupWithMaxLtvAndDebtReserve)!.id;
1830
+ console.log('Setting eModeGroup to', eModeGroup);
1831
+
1832
+ if (eModeGroup !== 0 && eModeGroup !== this.obligation?.state.elevationGroup) {
1833
+ newElevationGroup = eModeGroup;
1834
+ }
1835
+ }
1836
+ }
1837
+
1838
+ console.log('newElevationGroup', newElevationGroup, addAsSupportIx);
1839
+ if (newElevationGroup >= 0 && newElevationGroup !== this.obligation?.state.elevationGroup) {
1840
+ this.addRequestElevationIx(newElevationGroup, addAsSupportIx);
1841
+ this.addRefreshReserveIxs(allReservesExcludingCurrent, addAsSupportIx);
1842
+ this.addRefreshReserveIxs(currentReserveAddresses.toArray(), addAsSupportIx);
1843
+ this.addRefreshObligationIx(addAsSupportIx);
1844
+
1845
+ if (action === 'borrow') {
1846
+ this.obligation!.refreshedStats.potentialElevationGroupUpdate = newElevationGroup;
1847
+ }
1848
+ }
1849
+ } else if (
1850
+ action === 'deposit' &&
1851
+ overrideElevationGroupRequest !== undefined &&
1852
+ overrideElevationGroupRequest !== this.obligation?.state.elevationGroup
1853
+ ) {
1854
+ const addAsSupportIx: AuxiliaryIx = 'setup';
1855
+ console.log('Deposit: Requesting elevation group', overrideElevationGroupRequest);
1856
+ this.addRequestElevationIx(overrideElevationGroupRequest, addAsSupportIx);
1857
+ this.addRefreshReserveIxs(allReservesExcludingCurrent, addAsSupportIx);
1858
+ this.addRefreshReserveIxs(currentReserveAddresses.toArray(), addAsSupportIx);
1859
+ this.addRefreshObligationIx(addAsSupportIx);
1860
+ }
1861
+ }
1862
+
1863
+ if (addAsSupportIx === 'setup') {
1864
+ // If this is an setup ixn (therefore not an in-between), it means it's either a one off action
1865
+ // or the first of a two-token-action
1866
+ if (action === 'liquidate') {
1867
+ this.addRefreshFarmsForReserve([this.outflowReserve!], addAsSupportIx, ReserveFarmKind.Collateral);
1868
+ this.addRefreshFarmsForReserve([this.reserve], addAsSupportIx, ReserveFarmKind.Debt);
1869
+ } else if (
1870
+ action === 'depositAndBorrow' ||
1871
+ action === 'depositCollateral' ||
1872
+ action === 'withdraw' ||
1873
+ action === 'deposit'
1874
+ ) {
1875
+ this.addRefreshFarmsForReserve(
1876
+ currentReserves,
1877
+ addAsSupportIx,
1878
+ ReserveFarmKind.Collateral,
1879
+ undefined,
1880
+ twoTokenAction
1881
+ );
1882
+ } else if (action === 'repayAndWithdraw' || action === 'borrow' || action === 'repay') {
1883
+ this.addRefreshFarmsForReserve(
1884
+ currentReserves,
1885
+ addAsSupportIx,
1886
+ ReserveFarmKind.Debt,
1887
+ undefined,
1888
+ twoTokenAction
1889
+ );
1890
+ } else {
1891
+ throw new Error(`Could not decide on refresh farm for action ${action}`);
1892
+ }
1893
+ } else {
1894
+ // If this is an inbetween, it means it's part of a two-token-action
1895
+ // so we skip the refresh farm obligation of the first reserve as that operation already happened
1896
+ // add added to 'setup' ixns
1897
+ if (action === 'depositAndBorrow') {
1898
+ this.addRefreshFarmsForReserve([this.outflowReserve!], addAsSupportIx, ReserveFarmKind.Debt);
1899
+ } else if (action === 'repayAndWithdraw') {
1900
+ this.addRefreshFarmsForReserve([this.outflowReserve!], addAsSupportIx, ReserveFarmKind.Collateral);
1901
+ } else {
1902
+ throw new Error(`Could not decide on refresh farm for action ${action}`);
1903
+ }
1904
+ }
1905
+ }
1906
+ }
1907
+
1908
+ async addSupportIxs(
1909
+ action: ActionType,
1910
+ includeAtaIxns: boolean,
1911
+ requestElevationGroup: boolean,
1912
+ includeUserMetadata: boolean,
1913
+ addInitObligationForFarm: boolean,
1914
+ twoTokenAction: boolean = false,
1915
+ overrideElevationGroupRequest?: number
1916
+ ) {
1917
+ if (!['mint', 'redeem'].includes(action)) {
1918
+ const [, ownerUserMetadata] = await this.kaminoMarket.getUserMetadata(this.owner);
1919
+ if (!ownerUserMetadata && includeUserMetadata) {
1920
+ await this.addInitUserMetadataIxs();
1921
+ }
1922
+
1923
+ await this.addInitReferrerTokenStateIxs();
1924
+ await this.addInitObligationIxs();
1925
+ }
1926
+
1927
+ await this.addSupportIxsWithoutInitObligation(
1928
+ action,
1929
+ includeAtaIxns,
1930
+ 'setup',
1931
+ requestElevationGroup,
1932
+ addInitObligationForFarm,
1933
+ false,
1934
+ twoTokenAction,
1935
+ overrideElevationGroupRequest
1936
+ );
1937
+ }
1938
+
1939
+ private static optionalAccount(pubkey: PublicKey, programId: PublicKey = PROGRAM_ID): PublicKey {
1940
+ if (isNotNullPubkey(pubkey)) {
1941
+ return pubkey;
1942
+ } else {
1943
+ return programId;
1944
+ }
1945
+ }
1946
+
1947
+ private addRefreshReserveIxs(reserves: PublicKey[], addAsSupportIx: AuxiliaryIx = 'setup') {
1948
+ reserves.forEach((reserveAddress) => {
1949
+ const foundReserve = this.kaminoMarket.getReserveByAddress(reserveAddress);
1950
+ if (!foundReserve) {
1951
+ throw new Error(`Could not find reserve ${reserveAddress} in reserves`);
1952
+ }
1953
+
1954
+ const { state } = foundReserve;
1955
+
1956
+ const refreshReserveIx = refreshReserve(
1957
+ {
1958
+ lendingMarket: this.kaminoMarket.getAddress(),
1959
+ reserve: reserveAddress,
1960
+ pythOracle: KaminoAction.optionalAccount(
1961
+ state.config.tokenInfo.pythConfiguration.price,
1962
+ this.kaminoMarket.programId
1963
+ ),
1964
+ switchboardPriceOracle: KaminoAction.optionalAccount(
1965
+ state.config.tokenInfo.switchboardConfiguration.priceAggregator,
1966
+ this.kaminoMarket.programId
1967
+ ),
1968
+ switchboardTwapOracle: KaminoAction.optionalAccount(
1969
+ state.config.tokenInfo.switchboardConfiguration.twapAggregator,
1970
+ this.kaminoMarket.programId
1971
+ ),
1972
+ scopePrices: KaminoAction.optionalAccount(
1973
+ state.config.tokenInfo.scopeConfiguration.priceFeed,
1974
+ this.kaminoMarket.programId
1975
+ ),
1976
+ },
1977
+ this.kaminoMarket.programId
1978
+ );
1979
+
1980
+ if (addAsSupportIx === 'setup') {
1981
+ this.setupIxs.push(refreshReserveIx);
1982
+ this.setupIxsLabels.push(`RefreshReserve[${reserveAddress}]`);
1983
+ } else if (addAsSupportIx === 'inBetween') {
1984
+ this.inBetweenIxs.push(refreshReserveIx);
1985
+ this.inBetweenIxsLabels.push(`RefreshReserve[${reserveAddress}]`);
1986
+ } else {
1987
+ this.cleanupIxs.push(refreshReserveIx);
1988
+ this.cleanupIxsLabels.push(`RefreshReserve[${reserveAddress}]`);
1989
+ }
1990
+ });
1991
+ }
1992
+
1993
+ public static getRefreshAllReserves(kaminoMarket: KaminoMarket, reserves: PublicKey[]): TransactionInstruction[] {
1994
+ return reserves.map((reserveAddress): TransactionInstruction => {
1995
+ const foundReserve = kaminoMarket.getReserveByAddress(reserveAddress);
1996
+ if (!foundReserve) {
1997
+ throw new Error(`Could not find reserve ${reserveAddress} in reserves`);
1998
+ }
1999
+
2000
+ const { state } = foundReserve;
2001
+ return refreshReserve(
2002
+ {
2003
+ reserve: reserveAddress,
2004
+ lendingMarket: state.lendingMarket,
2005
+ pythOracle: this.optionalAccount(state.config.tokenInfo.pythConfiguration.price, kaminoMarket.programId),
2006
+ switchboardPriceOracle: this.optionalAccount(
2007
+ state.config.tokenInfo.switchboardConfiguration.priceAggregator,
2008
+ kaminoMarket.programId
2009
+ ),
2010
+ switchboardTwapOracle: this.optionalAccount(
2011
+ state.config.tokenInfo.switchboardConfiguration.twapAggregator,
2012
+ kaminoMarket.programId
2013
+ ),
2014
+ scopePrices: this.optionalAccount(
2015
+ state.config.tokenInfo.scopeConfiguration.priceFeed,
2016
+ kaminoMarket.programId
2017
+ ),
2018
+ },
2019
+ kaminoMarket.programId
2020
+ );
2021
+ });
2022
+ }
2023
+
2024
+ private addRefreshObligationIx(addAsSupportIx: AuxiliaryIx = 'setup', skipBorrowObligations: boolean = false) {
2025
+ const marketAddress = this.kaminoMarket.getAddress();
2026
+ const obligationPda = this.getObligationPda();
2027
+ const refreshObligationIx = refreshObligation(
2028
+ {
2029
+ lendingMarket: marketAddress,
2030
+ obligation: obligationPda,
2031
+ },
2032
+ this.kaminoMarket.programId
2033
+ );
2034
+
2035
+ const depositReservesList = this.getAdditionalDepositReservesList();
2036
+
2037
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
2038
+ return { pubkey: reserve, isSigner: false, isWritable: true };
2039
+ });
2040
+
2041
+ const preloadedBorrowReservesString = this.preLoadedBorrowReservesSameTx.map((reserve) => reserve.toString());
2042
+ const borrowReservesList = this.borrowReserves.filter(
2043
+ (reserve) => !preloadedBorrowReservesString.includes(reserve.toString())
2044
+ );
2045
+
2046
+ const borrowReserveAccountMetas = borrowReservesList.map((reserve) => {
2047
+ return { pubkey: reserve, isSigner: false, isWritable: true };
2048
+ });
2049
+
2050
+ const borrowReservesReferrerTokenStates = borrowReservesList
2051
+ .map((reserve) => {
2052
+ if (this.referrer.equals(PublicKey.default)) {
2053
+ return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: true };
2054
+ }
2055
+ const referrerTokenStateAddress = referrerTokenStatePda(this.referrer, reserve, this.kaminoMarket.programId)[0];
2056
+ return { pubkey: referrerTokenStateAddress, isSigner: false, isWritable: true };
2057
+ })
2058
+ .filter((x) => !x.pubkey.equals(this.kaminoMarket.programId));
2059
+
2060
+ refreshObligationIx.keys = refreshObligationIx.keys.concat([
2061
+ ...depositReserveAccountMetas,
2062
+ ...(skipBorrowObligations ? [] : [...borrowReserveAccountMetas, ...borrowReservesReferrerTokenStates]),
2063
+ ]);
2064
+
2065
+ if (addAsSupportIx === 'setup') {
2066
+ this.setupIxs.push(refreshObligationIx);
2067
+ this.setupIxsLabels.push(`RefreshObligation[${obligationPda.toString()}]`);
2068
+ } else if (addAsSupportIx === 'inBetween') {
2069
+ this.inBetweenIxs.push(refreshObligationIx);
2070
+ this.inBetweenIxsLabels.push(`RefreshObligation[${obligationPda.toString()}]`);
2071
+ } else {
2072
+ this.cleanupIxs.push(refreshObligationIx);
2073
+ this.cleanupIxsLabels.push(`RefreshObligation[${obligationPda.toString()}]`);
2074
+ }
2075
+ }
2076
+
2077
+ private addRequestElevationIx(
2078
+ elevationGroup: number,
2079
+ addAsSupportIx: AuxiliaryIx,
2080
+ skipBorrowObligations: boolean = false
2081
+ ) {
2082
+ const obligationPda = this.getObligationPda();
2083
+ const args: RequestElevationGroupArgs = {
2084
+ elevationGroup,
2085
+ };
2086
+ const accounts: RequestElevationGroupAccounts = {
2087
+ owner: this.owner,
2088
+ obligation: obligationPda,
2089
+ lendingMarket: this.kaminoMarket.getAddress(),
2090
+ };
2091
+
2092
+ const requestElevationGroupIx = requestElevationGroup(args, accounts, this.kaminoMarket.programId);
2093
+
2094
+ const depositReservesList = this.getAdditionalDepositReservesList();
2095
+
2096
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
2097
+ return { pubkey: reserve, isSigner: false, isWritable: true };
2098
+ });
2099
+
2100
+ const preloadedBorrowReservesString = this.preLoadedBorrowReservesSameTx.map((reserve) => reserve.toString());
2101
+ const borrowReservesList = this.borrowReserves.filter(
2102
+ (reserve) => !preloadedBorrowReservesString.includes(reserve.toString())
2103
+ );
2104
+
2105
+ const borrowReserveAccountMetas = borrowReservesList.map((reserve) => {
2106
+ return { pubkey: reserve, isSigner: false, isWritable: true };
2107
+ });
2108
+
2109
+ const borrowReservesReferrerTokenStates = borrowReservesList
2110
+ .map((reserve) => {
2111
+ if (this.referrer.equals(PublicKey.default)) {
2112
+ return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: true };
2113
+ }
2114
+ const reserveState = this.kaminoMarket.getReserveByAddress(reserve)!;
2115
+ const referrerTokenStateAddress = referrerTokenStatePda(
2116
+ this.referrer,
2117
+ reserveState.address,
2118
+ this.kaminoMarket.programId
2119
+ )[0];
2120
+ return { pubkey: referrerTokenStateAddress, isSigner: false, isWritable: true };
2121
+ })
2122
+ .filter((x) => !x.pubkey.equals(this.kaminoMarket.programId));
2123
+
2124
+ requestElevationGroupIx.keys = requestElevationGroupIx.keys.concat([
2125
+ ...depositReserveAccountMetas,
2126
+ ...(skipBorrowObligations ? [] : [...borrowReserveAccountMetas, ...borrowReservesReferrerTokenStates]),
2127
+ ]);
2128
+
2129
+ if (addAsSupportIx === 'setup') {
2130
+ this.setupIxs.push(requestElevationGroupIx);
2131
+ this.setupIxsLabels.push(`RequestElevation[${obligationPda}], elevation_group:${elevationGroup}`);
2132
+ } else if (addAsSupportIx === 'inBetween') {
2133
+ this.inBetweenIxs.push(requestElevationGroupIx);
2134
+ this.inBetweenIxsLabels.push(`RequestElevation[${obligationPda}], elevation_group:${elevationGroup}`);
2135
+ } else {
2136
+ this.cleanupIxs.push(requestElevationGroupIx);
2137
+ this.cleanupIxsLabels.push(`RequestElevation[${obligationPda}], elevation_group:${elevationGroup}`);
2138
+ }
2139
+ }
2140
+
2141
+ private addRefreshFarmsForReserve(
2142
+ reserves: KaminoReserve[],
2143
+ addAsSupportIx: AuxiliaryIx = 'setup',
2144
+ mode: typeof ReserveFarmKind.Collateral | typeof ReserveFarmKind.Debt,
2145
+ crank: PublicKey = this.payer,
2146
+ twoTokenAction: boolean = false
2147
+ ) {
2148
+ const BASE_SEED_USER_STATE = Buffer.from('user');
2149
+ const getPda = (farm: PublicKey) =>
2150
+ PublicKey.findProgramAddressSync(
2151
+ [BASE_SEED_USER_STATE, farm.toBytes(), this.getObligationPda().toBytes()],
2152
+ farmsId
2153
+ )[0];
2154
+
2155
+ const farms: [
2156
+ typeof ReserveFarmKind.Collateral | typeof ReserveFarmKind.Debt,
2157
+ PublicKey,
2158
+ PublicKey,
2159
+ KaminoReserve
2160
+ ][] = [];
2161
+
2162
+ for (const kaminoReserve of reserves) {
2163
+ if (mode === ReserveFarmKind.Collateral && !kaminoReserve.state.farmCollateral.equals(PublicKey.default)) {
2164
+ farms.push([
2165
+ ReserveFarmKind.Collateral,
2166
+ kaminoReserve.state.farmCollateral,
2167
+ getPda(kaminoReserve.state.farmCollateral),
2168
+ kaminoReserve,
2169
+ ]);
2170
+ }
2171
+ if (mode === ReserveFarmKind.Debt && !kaminoReserve.state.farmDebt.equals(PublicKey.default)) {
2172
+ farms.push([
2173
+ ReserveFarmKind.Debt,
2174
+ kaminoReserve.state.farmDebt,
2175
+ getPda(kaminoReserve.state.farmDebt),
2176
+ kaminoReserve,
2177
+ ]);
2178
+ }
2179
+ }
2180
+
2181
+ farms.forEach(
2182
+ (arg: [typeof ReserveFarmKind.Collateral | typeof ReserveFarmKind.Debt, PublicKey, PublicKey, KaminoReserve]) => {
2183
+ const args: RefreshObligationFarmsForReserveArgs = { mode: arg[0].discriminator };
2184
+ const accounts: RefreshObligationFarmsForReserveAccounts = {
2185
+ crank,
2186
+ obligation: this.getObligationPda(),
2187
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
2188
+ reserve: arg[3].address,
2189
+ reserveFarmState: arg[1],
2190
+ obligationFarmUserState: arg[2],
2191
+ lendingMarket: this.kaminoMarket.getAddress(),
2192
+ farmsProgram: farmsId,
2193
+ rent: SYSVAR_RENT_PUBKEY,
2194
+ systemProgram: SystemProgram.programId,
2195
+ };
2196
+ const refreshFarmForObligationix = refreshObligationFarmsForReserve(
2197
+ args,
2198
+ accounts,
2199
+ this.kaminoMarket.programId
2200
+ );
2201
+
2202
+ if (addAsSupportIx === 'setup') {
2203
+ this.setupIxs.push(refreshFarmForObligationix);
2204
+ this.setupIxsLabels.push(
2205
+ `RefreshFarmForObligation[${
2206
+ arg[0].kind
2207
+ }, res=${arg[3].address.toString()}, obl=${this.getObligationPda().toString()}]`
2208
+ );
2209
+ if (twoTokenAction) {
2210
+ // If two token action, this refresh needs to be the first inbetween ix
2211
+ this.inBetweenIxs.push(refreshFarmForObligationix);
2212
+ this.inBetweenIxsLabels.push(
2213
+ `RefreshFarmForObligation[${
2214
+ arg[0].kind
2215
+ }, res=${arg[3].address.toString()}, obl=${this.getObligationPda().toString()}]`
2216
+ );
2217
+ } else {
2218
+ this.refreshFarmsCleanupTxnIxs.push(refreshFarmForObligationix);
2219
+ this.refreshFarmsCleanupTxnIxsLabels.push(
2220
+ `RefreshFarmForObligation[${
2221
+ arg[0].kind
2222
+ }, res=${arg[3].address.toString()}, obl=${this.getObligationPda().toString()}]`
2223
+ );
2224
+ }
2225
+ } else if (addAsSupportIx === 'inBetween') {
2226
+ this.inBetweenIxs.push(refreshFarmForObligationix);
2227
+ this.inBetweenIxsLabels.push(
2228
+ `RefreshFarmForObligation[${
2229
+ arg[0].kind
2230
+ }, res=${arg[3].address.toString()}, obl=${this.getObligationPda().toString()}]`
2231
+ );
2232
+
2233
+ this.refreshFarmsCleanupTxnIxs.push(refreshFarmForObligationix);
2234
+ this.refreshFarmsCleanupTxnIxsLabels.push(
2235
+ `RefreshFarmForObligation[${
2236
+ arg[0].kind
2237
+ }, res=${arg[3].address.toString()}, obl=${this.getObligationPda().toString()}]`
2238
+ );
2239
+ }
2240
+ }
2241
+ );
2242
+ }
2243
+
2244
+ private addRefreshFarmsCleanupTxnIxsToCleanupIxs() {
2245
+ this.cleanupIxs.splice(0, 0, ...this.refreshFarmsCleanupTxnIxs);
2246
+ this.cleanupIxsLabels.splice(0, 0, ...this.refreshFarmsCleanupTxnIxsLabels);
2247
+ }
2248
+
2249
+ private async addInitObligationForFarm(
2250
+ reserve: KaminoReserve,
2251
+ mode: typeof ReserveFarmKind.Collateral | typeof ReserveFarmKind.Debt,
2252
+ addAsSupportIx: AuxiliaryIx = 'setup'
2253
+ ): Promise<void> {
2254
+ const BASE_SEED_USER_STATE = Buffer.from('user');
2255
+ const getPda = (farm: PublicKey) =>
2256
+ PublicKey.findProgramAddressSync(
2257
+ [BASE_SEED_USER_STATE, farm.toBytes(), this.getObligationPda().toBytes()],
2258
+ farmsId
2259
+ )[0];
2260
+
2261
+ const farms: [number, PublicKey, PublicKey][] = [];
2262
+
2263
+ if (mode === ReserveFarmKind.Collateral && isNotNullPubkey(reserve.state.farmCollateral)) {
2264
+ const pda = getPda(reserve.state.farmCollateral);
2265
+ const account = await this.kaminoMarket.getConnection().getAccountInfo(pda);
2266
+ if (!account) {
2267
+ farms.push([ReserveFarmKind.Collateral.discriminator, reserve.state.farmCollateral, pda]);
2268
+ }
2269
+ }
2270
+
2271
+ if (mode === ReserveFarmKind.Debt && isNotNullPubkey(reserve.state.farmDebt)) {
2272
+ const pda = getPda(reserve.state.farmDebt);
2273
+ const account = await this.kaminoMarket.getConnection().getAccountInfo(pda);
2274
+ if (!account) {
2275
+ farms.push([ReserveFarmKind.Debt.discriminator, reserve.state.farmDebt, getPda(reserve.state.farmDebt)]);
2276
+ }
2277
+ }
2278
+
2279
+ farms.forEach((arg: [number, PublicKey, PublicKey]) => {
2280
+ const args: InitObligationFarmsForReserveArgs = { mode: arg[0] };
2281
+ const accounts: InitObligationFarmsForReserveAccounts = {
2282
+ owner: this.obligation ? this.obligation.state.owner : this.owner,
2283
+ payer: this.owner,
2284
+ obligation: this.getObligationPda(),
2285
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
2286
+ reserve: reserve.address,
2287
+ reserveFarmState: arg[1],
2288
+ obligationFarm: arg[2],
2289
+ lendingMarket: this.kaminoMarket.getAddress(),
2290
+ farmsProgram: farmsId,
2291
+ rent: SYSVAR_RENT_PUBKEY,
2292
+ systemProgram: SystemProgram.programId,
2293
+ };
2294
+ const initObligationForFarm = initObligationFarmsForReserve(args, accounts, this.kaminoMarket.programId);
2295
+ if (addAsSupportIx === 'setup') {
2296
+ this.setupIxs.push(initObligationForFarm);
2297
+ this.setupIxsLabels.push(
2298
+ `InitObligationForFarm[${reserve.address.toString()}, ${this.getObligationPda().toString()}]`
2299
+ );
2300
+ } else if (addAsSupportIx === 'inBetween') {
2301
+ this.inBetweenIxs.push(initObligationForFarm);
2302
+ this.inBetweenIxsLabels.push(
2303
+ `InitObligationForFarm[${reserve.address.toString()}, ${this.getObligationPda().toString()}]`
2304
+ );
2305
+ }
2306
+ });
2307
+ }
2308
+
2309
+ private async addInitObligationIxs() {
2310
+ if (!this.obligation) {
2311
+ const obligationPda = this.getObligationPda();
2312
+ const [userMetadataAddress, _bump] = userMetadataPda(this.owner, this.kaminoMarket.programId);
2313
+ const initObligationIx = initObligation(
2314
+ {
2315
+ args: {
2316
+ tag: this.obligationType!.toArgs().tag,
2317
+ id: this.obligationType!.toArgs().id,
2318
+ },
2319
+ },
2320
+ {
2321
+ obligationOwner: this.owner,
2322
+ feePayer: this.payer,
2323
+ obligation: obligationPda,
2324
+ lendingMarket: this.kaminoMarket.getAddress(),
2325
+ seed1Account: this.obligationType!.toArgs().seed1,
2326
+ seed2Account: this.obligationType!.toArgs().seed2,
2327
+ ownerUserMetadata: userMetadataAddress,
2328
+ rent: SYSVAR_RENT_PUBKEY,
2329
+ systemProgram: SystemProgram.programId,
2330
+ },
2331
+ this.kaminoMarket.programId
2332
+ );
2333
+ this.setupIxs.push(initObligationIx);
2334
+ this.setupIxsLabels.push(`InitObligation[${obligationPda.toString()}]`);
2335
+ }
2336
+ }
2337
+
2338
+ private async addInitUserMetadataIxs() {
2339
+ const [createLutIx, lookupTableAddress] = await createLookupTableIx(this.kaminoMarket.getConnection(), this.owner);
2340
+ this.setupIxs.push(createLutIx);
2341
+ this.setupIxsLabels.push(`createUserLutIx[${lookupTableAddress.toString()}]`);
2342
+ const [userMetadataAddress, _bump] = userMetadataPda(this.owner, this.kaminoMarket.programId);
2343
+ const referrerUserMetadataAddress = this.referrer.equals(PublicKey.default)
2344
+ ? this.kaminoMarket.programId
2345
+ : userMetadataPda(this.referrer, this.kaminoMarket.programId)[0];
2346
+ const initUserMetadataIx = initUserMetadata(
2347
+ {
2348
+ userLookupTable: lookupTableAddress,
2349
+ },
2350
+ {
2351
+ owner: this.owner,
2352
+ feePayer: this.payer,
2353
+ userMetadata: userMetadataAddress,
2354
+ referrerUserMetadata: referrerUserMetadataAddress,
2355
+ rent: SYSVAR_RENT_PUBKEY,
2356
+ systemProgram: SystemProgram.programId,
2357
+ },
2358
+ this.kaminoMarket.programId
2359
+ );
2360
+ this.setupIxs.push(initUserMetadataIx);
2361
+ this.setupIxsLabels.push(`initUserMetadata[${userMetadataAddress.toString()}]`);
2362
+ }
2363
+
2364
+ private async addInitReferrerTokenStateIxs(reservesArr: KaminoReserve[] = []) {
2365
+ if (this.referrer.equals(PublicKey.default)) {
2366
+ return;
2367
+ }
2368
+
2369
+ const outflowReserve = this.outflowReserve?.address ? [this.outflowReserve.address] : [];
2370
+
2371
+ const reserves =
2372
+ reservesArr.length !== 0
2373
+ ? reservesArr.map((reserve) => reserve.address)
2374
+ : new PublicKeySet<PublicKey>([this.reserve.address, ...outflowReserve]).toArray();
2375
+ const tokenStatesToCreate: [PublicKey, PublicKey][] = [];
2376
+ for (const reserve of reserves) {
2377
+ if (!reserve) {
2378
+ continue;
2379
+ }
2380
+
2381
+ const referrerTokenStateAddress = referrerTokenStatePda(this.referrer, reserve, this.kaminoMarket.programId)[0];
2382
+
2383
+ if (!(await checkIfAccountExists(this.kaminoMarket.getConnection(), referrerTokenStateAddress))) {
2384
+ tokenStatesToCreate.push([referrerTokenStateAddress, reserve]);
2385
+ }
2386
+ }
2387
+
2388
+ tokenStatesToCreate.forEach(([referrerTokenStateAddress, reserveAddress]) => {
2389
+ const initreferrerTokenStateIx = initReferrerTokenState(
2390
+ {
2391
+ referrer: this.referrer,
2392
+ },
2393
+ {
2394
+ lendingMarket: this.kaminoMarket.getAddress(),
2395
+ payer: this.owner,
2396
+ reserve: reserveAddress,
2397
+ referrerTokenState: referrerTokenStateAddress,
2398
+ rent: SYSVAR_RENT_PUBKEY,
2399
+ systemProgram: SystemProgram.programId,
2400
+ },
2401
+ this.kaminoMarket.programId
2402
+ );
2403
+
2404
+ this.setupIxs.unshift(initreferrerTokenStateIx);
2405
+ this.setupIxsLabels.unshift(
2406
+ `InitReferrerTokenState[${referrerTokenStateAddress.toString()} res=${reserveAddress}]`
2407
+ );
2408
+ });
2409
+ }
2410
+
2411
+ private addWithdrawReferrerFeesIxs() {
2412
+ const referrerTokenStateAddress = referrerTokenStatePda(
2413
+ this.owner,
2414
+ this.reserve.address,
2415
+ this.kaminoMarket.programId
2416
+ )[0];
2417
+
2418
+ const withdrawReferrerFeesIx = withdrawReferrerFees(
2419
+ {
2420
+ referrer: this.owner,
2421
+ lendingMarket: this.kaminoMarket.getAddress(),
2422
+ reserve: this.reserve.address,
2423
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
2424
+ referrerTokenState: referrerTokenStateAddress,
2425
+ reserveSupplyLiquidity: this.reserve.state.liquidity.supplyVault,
2426
+ referrerTokenAccount: this.userTokenAccountAddress,
2427
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
2428
+ tokenProgram: this.reserve.getLiquidityTokenProgram(),
2429
+ },
2430
+ this.kaminoMarket.programId
2431
+ );
2432
+
2433
+ this.lendingIxs.push(withdrawReferrerFeesIx);
2434
+ this.lendingIxsLabels.push(`WithdrawReferrerFeesIx[${this.owner.toString()}]`);
2435
+ }
2436
+
2437
+ private addComputeBudgetIxn(units: number) {
2438
+ this.setupIxs.push(buildComputeBudgetIx(units));
2439
+ this.setupIxsLabels.push(`AddComputeBudget[${units}]`);
2440
+ }
2441
+
2442
+ private async addAtaIxs(action: ActionType) {
2443
+ if (this.mint.equals(WRAPPED_SOL_MINT) || this.secondaryMint?.equals(WRAPPED_SOL_MINT)) {
2444
+ await this.updateWSOLAccount(action);
2445
+ }
2446
+
2447
+ if ((action === 'withdraw' || action === 'borrow' || action === 'redeem') && !this.mint.equals(WRAPPED_SOL_MINT)) {
2448
+ const userTokenAccountInfo = await this.kaminoMarket.getConnection().getAccountInfo(this.userTokenAccountAddress);
2449
+
2450
+ if (!userTokenAccountInfo) {
2451
+ const [, createUserTokenAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2452
+ this.owner,
2453
+ this.reserve.getLiquidityMint(),
2454
+ this.owner,
2455
+ this.reserve.getLiquidityTokenProgram(),
2456
+ this.userTokenAccountAddress
2457
+ );
2458
+
2459
+ if (this.positions === POSITION_LIMIT) {
2460
+ this.preTxnIxs.push(createUserTokenAccountIx);
2461
+ this.preTxnIxsLabels.push(`CreateLiquidityUserAta[${this.owner}]`);
2462
+ } else {
2463
+ this.setupIxs.unshift(createUserTokenAccountIx);
2464
+ this.setupIxsLabels.unshift(`CreateLiquidityUserAta[${this.owner}]`);
2465
+ }
2466
+ }
2467
+ }
2468
+
2469
+ if (action === 'liquidate') {
2470
+ const userTokenAccountInfo = await this.kaminoMarket.getConnection().getAccountInfo(this.userTokenAccountAddress);
2471
+
2472
+ if (!this.outflowReserve) {
2473
+ throw new Error(`Outflow reserve state not found ${this.mint}`);
2474
+ }
2475
+
2476
+ if (!userTokenAccountInfo) {
2477
+ const [, createUserTokenAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2478
+ this.owner,
2479
+ this.outflowReserve.getLiquidityMint(),
2480
+ this.owner,
2481
+ this.outflowReserve.getLiquidityTokenProgram(),
2482
+ this.userTokenAccountAddress
2483
+ );
2484
+ if (this.positions === POSITION_LIMIT && this.mint.equals(WRAPPED_SOL_MINT)) {
2485
+ this.preTxnIxs.push(createUserTokenAccountIx);
2486
+ this.preTxnIxsLabels.push(`CreateUserAta[${this.userTokenAccountAddress.toBase58()}]`);
2487
+ } else {
2488
+ this.setupIxs.unshift(createUserTokenAccountIx);
2489
+ this.setupIxsLabels.unshift(`CreateUserAta[${this.userTokenAccountAddress.toBase58()}]`);
2490
+ }
2491
+ }
2492
+
2493
+ const userCollateralAccountInfo = await this.kaminoMarket
2494
+ .getConnection()
2495
+ .getAccountInfo(this.userCollateralAccountAddress);
2496
+ if (!userCollateralAccountInfo) {
2497
+ const [, createUserCollateralAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2498
+ this.owner,
2499
+ this.outflowReserve.getCTokenMint(),
2500
+ this.owner,
2501
+ TOKEN_PROGRAM_ID,
2502
+ this.userCollateralAccountAddress
2503
+ );
2504
+
2505
+ if (this.positions === POSITION_LIMIT && this.mint.equals(WRAPPED_SOL_MINT)) {
2506
+ this.preTxnIxs.push(createUserCollateralAccountIx);
2507
+ this.preTxnIxsLabels.push(`CreateCollateralUserAta[${this.userCollateralAccountAddress.toString()}]`);
2508
+ } else {
2509
+ this.setupIxs.unshift(createUserCollateralAccountIx);
2510
+ this.setupIxsLabels.unshift(`CreateCollateralUserAta[${this.userCollateralAccountAddress.toString()}]`);
2511
+ }
2512
+ }
2513
+
2514
+ if (!this.additionalTokenAccountAddress) {
2515
+ throw new Error(`Additional token account address not found ${this.mint}`);
2516
+ }
2517
+ }
2518
+
2519
+ if (
2520
+ action === 'depositAndBorrow' ||
2521
+ (action === 'repayAndWithdraw' && !this.secondaryMint?.equals(WRAPPED_SOL_MINT))
2522
+ ) {
2523
+ if (!this.additionalTokenAccountAddress) {
2524
+ throw new Error(`Additional token account address not found ${this.secondaryMint}`);
2525
+ }
2526
+
2527
+ if (!this.outflowReserve) {
2528
+ throw new Error(`Outflow reserve state not found ${this.mint}`);
2529
+ }
2530
+
2531
+ const additionalUserTokenAccountInfo = await this.kaminoMarket
2532
+ .getConnection()
2533
+ .getAccountInfo(this.additionalTokenAccountAddress);
2534
+
2535
+ if (!additionalUserTokenAccountInfo) {
2536
+ const [, createUserTokenAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2537
+ this.owner,
2538
+ this.outflowReserve.getLiquidityMint(),
2539
+ this.owner,
2540
+ this.outflowReserve.getLiquidityTokenProgram(),
2541
+ this.additionalTokenAccountAddress
2542
+ );
2543
+
2544
+ this.setupIxs.unshift(createUserTokenAccountIx);
2545
+ this.setupIxsLabels.unshift(`CreateAdditionalUserTokenAta[${this.owner}]`);
2546
+ }
2547
+ }
2548
+
2549
+ if (action === 'withdraw' || action === 'mint' || action === 'deposit' || action === 'repayAndWithdraw') {
2550
+ const userTokenAccountInfo = await this.kaminoMarket.getConnection().getAccountInfo(this.userTokenAccountAddress);
2551
+
2552
+ // TODO: Might need to remove this
2553
+ if (!userTokenAccountInfo) {
2554
+ const [, createUserTokenAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2555
+ this.owner,
2556
+ this.reserve.getLiquidityMint(),
2557
+ this.owner,
2558
+ this.reserve.getLiquidityTokenProgram(),
2559
+ this.userTokenAccountAddress
2560
+ );
2561
+ this.preTxnIxs.push(createUserTokenAccountIx);
2562
+ this.preTxnIxsLabels.push(`CreateUserAta[${this.userTokenAccountAddress.toBase58()}]`);
2563
+ }
2564
+ }
2565
+ if (action === 'mint') {
2566
+ const userCollateralAccountInfo = await this.kaminoMarket
2567
+ .getConnection()
2568
+ .getAccountInfo(this.userCollateralAccountAddress);
2569
+
2570
+ if (!userCollateralAccountInfo) {
2571
+ const collateralMintPubkey = this.reserve.getCTokenMint();
2572
+ const [, createUserCollateralAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2573
+ this.owner,
2574
+ collateralMintPubkey,
2575
+ this.owner,
2576
+ TOKEN_PROGRAM_ID,
2577
+ this.userCollateralAccountAddress
2578
+ );
2579
+
2580
+ if (this.positions === POSITION_LIMIT && this.mint.equals(WRAPPED_SOL_MINT)) {
2581
+ this.preTxnIxs.push(createUserCollateralAccountIx);
2582
+ this.preTxnIxsLabels.push(`CreateCollateralUserAta[${this.userCollateralAccountAddress.toString()}]`);
2583
+ } else {
2584
+ this.setupIxs.unshift(createUserCollateralAccountIx);
2585
+ this.setupIxsLabels.unshift(`CreateCollateralUserAta[${this.userCollateralAccountAddress.toString()}]`);
2586
+ }
2587
+ }
2588
+ }
2589
+ }
2590
+
2591
+ private async updateWSOLAccount(action: ActionType) {
2592
+ const preIxs: Array<TransactionInstruction> = [];
2593
+ const postIxs: Array<TransactionInstruction> = [];
2594
+ const preIxsLabels: Array<string> = [];
2595
+ const postIxsLabels: Array<string> = [];
2596
+
2597
+ if (action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
2598
+ return;
2599
+ }
2600
+
2601
+ let safeRepay = new BN(this.amount);
2602
+
2603
+ if (this.obligation && action === 'repay' && this.amount.eq(new BN(U64_MAX))) {
2604
+ const borrow = this.obligation.state.borrows.find(
2605
+ (borrow) => borrow.borrowReserve.toString() === this.reserve.address.toString()
2606
+ );
2607
+
2608
+ if (!borrow) {
2609
+ throw Error(`Unable to find obligation borrow to repay for ${this.obligation.state.owner.toBase58()}`);
2610
+ }
2611
+
2612
+ const cumulativeBorrowRateObligation = KaminoObligation.getCumulativeBorrowRate(borrow);
2613
+ const cumulativeBorrowRateReserve = this.reserve.getEstimatedCumulativeBorrowRate(
2614
+ this.currentSlot,
2615
+ this.kaminoMarket.state.referralFeeBps
2616
+ );
2617
+ // TODO: shouldn't this calc be added to all other stuff as well?
2618
+ safeRepay = new BN(
2619
+ Math.floor(
2620
+ KaminoObligation.getBorrowAmount(borrow)
2621
+ .mul(cumulativeBorrowRateReserve)
2622
+ .div(cumulativeBorrowRateObligation)
2623
+ .add(new Decimal(SOL_PADDING_FOR_INTEREST.toString()))
2624
+ .toNumber()
2625
+ ).toString()
2626
+ );
2627
+ }
2628
+
2629
+ let userTokenAccountAddress = this.userTokenAccountAddress;
2630
+ if (this.secondaryMint?.equals(WRAPPED_SOL_MINT)) {
2631
+ if (!this.additionalTokenAccountAddress) {
2632
+ throw new Error(`Additional token account address not found ${this.secondaryMint}`);
2633
+ }
2634
+ userTokenAccountAddress = this.additionalTokenAccountAddress;
2635
+ }
2636
+
2637
+ const userWSOLAccountInfo = await this.kaminoMarket.getConnection().getAccountInfo(userTokenAccountAddress);
2638
+
2639
+ const rentExempt = await this.kaminoMarket.getConnection().getMinimumBalanceForRentExemption(165);
2640
+
2641
+ // Add rent exemption lamports for WSOL accounts that need to be pre-funded for inflow/send transactions
2642
+ const sendAction =
2643
+ action === 'deposit' ||
2644
+ action === 'repay' ||
2645
+ action === 'mint' ||
2646
+ (action === 'liquidate' && this.secondaryMint?.equals(WRAPPED_SOL_MINT)); // only sync WSOL amount if liquidator repays SOL which is secondaryMint
2647
+
2648
+ const transferLamportsIx = SystemProgram.transfer({
2649
+ fromPubkey: this.owner,
2650
+ toPubkey: userTokenAccountAddress,
2651
+ lamports: (userWSOLAccountInfo ? 0 : rentExempt) + (sendAction ? parseInt(safeRepay.toString(), 10) : 0),
2652
+ });
2653
+ preIxs.push(transferLamportsIx);
2654
+ preIxsLabels.push(`TransferLamportsToUserAtaSOL[${userTokenAccountAddress}]`);
2655
+
2656
+ const closeWSOLAccountIx = createCloseAccountInstruction(
2657
+ userTokenAccountAddress,
2658
+ this.owner,
2659
+ this.owner,
2660
+ [],
2661
+ TOKEN_PROGRAM_ID
2662
+ );
2663
+
2664
+ const syncIx = syncNative(userTokenAccountAddress);
2665
+ if (userWSOLAccountInfo) {
2666
+ if (sendAction) {
2667
+ preIxs.push(syncIx);
2668
+ preIxsLabels.push(`SyncUserAtaSOL[${userTokenAccountAddress}]`);
2669
+ } else {
2670
+ postIxs.push(closeWSOLAccountIx);
2671
+ postIxsLabels.push(`CloseUserAtaSOL[${userTokenAccountAddress}]`);
2672
+ }
2673
+ } else {
2674
+ const [, createUserWSOLAccountIx] = createAssociatedTokenAccountIdempotentInstruction(
2675
+ this.owner,
2676
+ NATIVE_MINT,
2677
+ this.owner,
2678
+ TOKEN_PROGRAM_ID,
2679
+ userTokenAccountAddress
2680
+ );
2681
+ preIxs.push(createUserWSOLAccountIx);
2682
+ preIxsLabels.push(`CreateUserAtaSOL[${userTokenAccountAddress}]`);
2683
+ preIxs.push(syncIx);
2684
+ preIxsLabels.push(`SyncUserAtaSOL[${userTokenAccountAddress}]`);
2685
+ postIxs.push(closeWSOLAccountIx);
2686
+ postIxsLabels.push(`CloseUserAtaSOL[${userTokenAccountAddress}]`);
2687
+ }
2688
+
2689
+ // TODO: Consider for liquidations and other types of actions if we have to split up some ixs in 2-3 txs
2690
+ // if (this.positions && this.positions >= POSITION_LIMIT) {
2691
+ // this.preTxnIxs.push(...preIxs);
2692
+ // this.preTxnIxsLabels.push(...preIxsLabels);
2693
+ // this.postTxnIxs.push(...postIxs);
2694
+ // this.postTxnIxsLabels.push(...postIxsLabels);
2695
+ // } else {
2696
+ // }
2697
+ this.setupIxs.unshift(...preIxs);
2698
+ this.setupIxsLabels.unshift(...preIxsLabels);
2699
+ this.cleanupIxs.push(...postIxs);
2700
+ this.cleanupIxsLabels.push(...postIxsLabels);
2701
+ }
2702
+
2703
+ static async initializeMultiTokenAction(
2704
+ kaminoMarket: KaminoMarket,
2705
+ action: ActionType,
2706
+ inflowAmount: string | BN,
2707
+ inflowTokenMint: PublicKey,
2708
+ outflowTokenMint: PublicKey,
2709
+ payer: PublicKey,
2710
+ obligationOwner: PublicKey,
2711
+ obligation: KaminoObligation | ObligationType,
2712
+ outflowAmount?: string | BN,
2713
+ referrer: PublicKey = PublicKey.default,
2714
+ currentSlot: number = 0
2715
+ ) {
2716
+ const inflowReserve = kaminoMarket.getReserveByMint(inflowTokenMint);
2717
+ const outflowReserve = kaminoMarket.getReserveByMint(outflowTokenMint);
2718
+
2719
+ if (!outflowReserve || !inflowReserve) {
2720
+ throw new Error('reserve states are not fetched');
2721
+ }
2722
+
2723
+ const {
2724
+ userTokenAccountAddress: userOutflowTokenAccountAddress,
2725
+ userCollateralAccountAddress: userOutflowCollateralAccountAddress,
2726
+ } = KaminoAction.getUserAccountAddresses(payer, outflowReserve.state);
2727
+
2728
+ const {
2729
+ userTokenAccountAddress: userInflowTokenAccountAddress,
2730
+ userCollateralAccountAddress: userInflowCollateralAccountAddress,
2731
+ } = KaminoAction.getUserAccountAddresses(payer, inflowReserve.state);
2732
+
2733
+ const { kaminoObligation, depositReserves, borrowReserves, distinctReserveCount } =
2734
+ await KaminoAction.loadObligation(
2735
+ action,
2736
+ kaminoMarket,
2737
+ obligationOwner,
2738
+ inflowReserve.address,
2739
+ obligation,
2740
+ outflowReserve.address
2741
+ );
2742
+ const referrerKey = await this.getReferrerKey(kaminoMarket, payer, kaminoObligation, referrer);
2743
+
2744
+ let userTokenAccountAddress: PublicKey;
2745
+ let userCollateralAccountAddress: PublicKey;
2746
+ let additionalUserTokenAccountAddress: PublicKey;
2747
+ let secondaryMint: PublicKey;
2748
+ let primaryMint: PublicKey;
2749
+
2750
+ if (action === 'liquidate') {
2751
+ userTokenAccountAddress = userOutflowTokenAccountAddress;
2752
+ userCollateralAccountAddress = userOutflowCollateralAccountAddress;
2753
+ additionalUserTokenAccountAddress = userInflowTokenAccountAddress;
2754
+ primaryMint = outflowTokenMint;
2755
+ secondaryMint = inflowTokenMint;
2756
+ } else if (action === 'depositAndBorrow') {
2757
+ userTokenAccountAddress = userInflowTokenAccountAddress;
2758
+ userCollateralAccountAddress = userInflowCollateralAccountAddress;
2759
+ additionalUserTokenAccountAddress = userOutflowTokenAccountAddress;
2760
+ primaryMint = inflowTokenMint;
2761
+ secondaryMint = outflowTokenMint;
2762
+ } else if (action === 'repayAndWithdraw') {
2763
+ primaryMint = inflowTokenMint;
2764
+ secondaryMint = outflowTokenMint;
2765
+ userTokenAccountAddress = userInflowTokenAccountAddress;
2766
+ userCollateralAccountAddress = userOutflowCollateralAccountAddress;
2767
+ additionalUserTokenAccountAddress = userOutflowTokenAccountAddress;
2768
+ } else {
2769
+ throw new Error('Invalid action');
2770
+ }
2771
+
2772
+ return new KaminoAction(
2773
+ kaminoMarket,
2774
+ payer,
2775
+ kaminoObligation || obligation,
2776
+ userTokenAccountAddress,
2777
+ userCollateralAccountAddress,
2778
+ primaryMint,
2779
+ distinctReserveCount,
2780
+ inflowAmount,
2781
+ depositReserves,
2782
+ borrowReserves,
2783
+ inflowReserve,
2784
+ currentSlot,
2785
+ secondaryMint,
2786
+ additionalUserTokenAccountAddress,
2787
+ outflowReserve,
2788
+ outflowAmount,
2789
+ referrerKey
2790
+ );
2791
+ }
2792
+
2793
+ static async initializeWithdrawReferrerFees(
2794
+ mint: PublicKey,
2795
+ owner: PublicKey,
2796
+ kaminoMarket: KaminoMarket,
2797
+ currentSlot: number = 0
2798
+ ) {
2799
+ const reserve = kaminoMarket.getReserveByMint(mint);
2800
+ if (reserve === undefined) {
2801
+ throw new Error(`Reserve ${mint} not found in market ${kaminoMarket.getAddress().toBase58()}`);
2802
+ }
2803
+
2804
+ const { atas, createAtasIxns } = await getAtasWithCreateIxnsIfMissing(
2805
+ kaminoMarket.getConnection(),
2806
+ owner,
2807
+ [reserve.getLiquidityMint()],
2808
+ [reserve.getLiquidityTokenProgram()]
2809
+ );
2810
+
2811
+ const userTokenAccountAddress = atas[0];
2812
+
2813
+ return {
2814
+ axn: new KaminoAction(
2815
+ kaminoMarket,
2816
+ owner,
2817
+ new VanillaObligation(kaminoMarket.programId),
2818
+ userTokenAccountAddress,
2819
+ PublicKey.default,
2820
+ mint,
2821
+ 0,
2822
+ new BN(0),
2823
+ [],
2824
+ [],
2825
+ reserve,
2826
+ currentSlot,
2827
+ undefined,
2828
+ undefined,
2829
+ undefined,
2830
+ undefined,
2831
+ undefined
2832
+ ),
2833
+ createAtasIxns,
2834
+ };
2835
+ }
2836
+
2837
+ getObligationPda(): PublicKey {
2838
+ return this.obligation
2839
+ ? this.obligation.obligationAddress
2840
+ : this.obligationType!.toPda(this.kaminoMarket.getAddress(), this.owner);
2841
+ }
2842
+
2843
+ getAdditionalDepositReservesList(): PublicKey[] {
2844
+ const depositReservesList = this.depositReserves;
2845
+
2846
+ // check if there's any member in the preloadedDepositReserves that is not in the depositReserves
2847
+ // if so, add it to the depositReserves
2848
+ for (let i = 0; i < this.preLoadedDepositReservesSameTx.length; i++) {
2849
+ const preloadedDepositReserve = this.preLoadedDepositReservesSameTx[i];
2850
+
2851
+ // Check if the depositReserves array contains the current preloadedDepositReserve
2852
+ const found = this.depositReserves.some((depositReserve) => {
2853
+ return depositReserve.equals(preloadedDepositReserve);
2854
+ });
2855
+
2856
+ // If not found, push the current preloadedDepositReserve to the depositReserves array
2857
+ if (!found) {
2858
+ depositReservesList.push(this.preLoadedDepositReservesSameTx[i]);
2859
+ }
2860
+ }
2861
+
2862
+ return depositReservesList;
2863
+ }
2864
+
2865
+ private static async getReferrerKey(
2866
+ kaminoMarket: KaminoMarket,
2867
+ owner: PublicKey,
2868
+ kaminoObligation: KaminoObligation | null,
2869
+ referrer: PublicKey
2870
+ ) {
2871
+ let referrerKey = referrer;
2872
+ if (!referrer || referrer.equals(PublicKey.default)) {
2873
+ if (kaminoObligation === null) {
2874
+ const [_, userMetadata] = await kaminoMarket.getUserMetadata(owner);
2875
+ if (userMetadata) {
2876
+ referrerKey = userMetadata.referrer;
2877
+ }
2878
+ } else {
2879
+ referrerKey = kaminoObligation.state.referrer;
2880
+ }
2881
+ }
2882
+ return referrerKey;
2883
+ }
2884
+ }