@eulerxyz/euler-v2-sdk 0.1.1-beta → 0.1.3-beta

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 (333) hide show
  1. package/README.md +11 -9
  2. package/dist/src/entities/Account.d.ts +26 -9
  3. package/dist/src/entities/Account.d.ts.map +1 -0
  4. package/dist/src/entities/Account.js +61 -44
  5. package/dist/src/entities/Account.js.map +1 -1
  6. package/dist/src/entities/ERC4626Vault.d.ts +1 -0
  7. package/dist/src/entities/ERC4626Vault.d.ts.map +1 -0
  8. package/dist/src/entities/EVault.d.ts +1 -0
  9. package/dist/src/entities/EVault.d.ts.map +1 -0
  10. package/dist/src/entities/EulerEarn.d.ts +1 -0
  11. package/dist/src/entities/EulerEarn.d.ts.map +1 -0
  12. package/dist/src/entities/EulerLabels.d.ts +6 -11
  13. package/dist/src/entities/EulerLabels.d.ts.map +1 -0
  14. package/dist/src/entities/Portfolio.d.ts +133 -0
  15. package/dist/src/entities/Portfolio.d.ts.map +1 -0
  16. package/dist/src/entities/Portfolio.js +304 -0
  17. package/dist/src/entities/Portfolio.js.map +1 -0
  18. package/dist/src/entities/SecuritizeCollateralVault.d.ts +1 -0
  19. package/dist/src/entities/SecuritizeCollateralVault.d.ts.map +1 -0
  20. package/dist/src/entities/Wallet.d.ts +1 -0
  21. package/dist/src/entities/Wallet.d.ts.map +1 -0
  22. package/dist/src/index.d.ts +5 -1
  23. package/dist/src/index.d.ts.map +1 -0
  24. package/dist/src/index.js +4 -1
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/plugins/batchSimulation.d.ts +1 -0
  27. package/dist/src/plugins/batchSimulation.d.ts.map +1 -0
  28. package/dist/src/plugins/index.d.ts +1 -0
  29. package/dist/src/plugins/index.d.ts.map +1 -0
  30. package/dist/src/plugins/keyring/index.d.ts +1 -0
  31. package/dist/src/plugins/keyring/index.d.ts.map +1 -0
  32. package/dist/src/plugins/keyring/keyringPlugin.d.ts +2 -1
  33. package/dist/src/plugins/keyring/keyringPlugin.d.ts.map +1 -0
  34. package/dist/src/plugins/keyring/keyringPlugin.js +12 -3
  35. package/dist/src/plugins/keyring/keyringPlugin.js.map +1 -1
  36. package/dist/src/plugins/pyth/index.d.ts +1 -0
  37. package/dist/src/plugins/pyth/index.d.ts.map +1 -0
  38. package/dist/src/plugins/pyth/pythPlugin.d.ts +1 -0
  39. package/dist/src/plugins/pyth/pythPlugin.d.ts.map +1 -0
  40. package/dist/src/plugins/types.d.ts +1 -0
  41. package/dist/src/plugins/types.d.ts.map +1 -0
  42. package/dist/src/sdk/buildSDK.d.ts +4 -3
  43. package/dist/src/sdk/buildSDK.d.ts.map +1 -0
  44. package/dist/src/sdk/buildSDK.js +15 -7
  45. package/dist/src/sdk/buildSDK.js.map +1 -1
  46. package/dist/src/sdk/defaultConfig.d.ts +1 -0
  47. package/dist/src/sdk/defaultConfig.d.ts.map +1 -0
  48. package/dist/src/sdk/defaultConfig.js +27 -28
  49. package/dist/src/sdk/defaultConfig.js.map +1 -1
  50. package/dist/src/sdk/sdk.d.ts +6 -5
  51. package/dist/src/sdk/sdk.d.ts.map +1 -0
  52. package/dist/src/sdk/sdk.js +2 -2
  53. package/dist/src/sdk/sdk.js.map +1 -1
  54. package/dist/src/services/abiService/abiService.d.ts +1 -0
  55. package/dist/src/services/abiService/abiService.d.ts.map +1 -0
  56. package/dist/src/services/abiService/index.d.ts +1 -0
  57. package/dist/src/services/abiService/index.d.ts.map +1 -0
  58. package/dist/src/services/accountService/accountService.d.ts +1 -0
  59. package/dist/src/services/accountService/accountService.d.ts.map +1 -0
  60. package/dist/src/services/accountService/accountService.js.map +1 -1
  61. package/dist/src/services/accountService/accountServiceConfig.d.ts +1 -0
  62. package/dist/src/services/accountService/accountServiceConfig.d.ts.map +1 -0
  63. package/dist/src/services/accountService/adapters/accountOnchainAdapter/abis/accountLensAbi.d.ts +1 -0
  64. package/dist/src/services/accountService/adapters/accountOnchainAdapter/abis/accountLensAbi.d.ts.map +1 -0
  65. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountInfoConverter.d.ts +1 -0
  66. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountInfoConverter.d.ts.map +1 -0
  67. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountInfoConverter.js +23 -8
  68. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountInfoConverter.js.map +1 -1
  69. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountLensTypes.d.ts +1 -0
  70. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountLensTypes.d.ts.map +1 -0
  71. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountOnchainAdapter.d.ts +1 -0
  72. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountOnchainAdapter.d.ts.map +1 -0
  73. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountVaultsSubgraphAdapter.d.ts +1 -0
  74. package/dist/src/services/accountService/adapters/accountOnchainAdapter/accountVaultsSubgraphAdapter.d.ts.map +1 -0
  75. package/dist/src/services/accountService/adapters/accountOutputNormalization.d.ts +1 -0
  76. package/dist/src/services/accountService/adapters/accountOutputNormalization.d.ts.map +1 -0
  77. package/dist/src/services/accountService/adapters/accountV3Adapter/accountV3Adapter.d.ts +8 -1
  78. package/dist/src/services/accountService/adapters/accountV3Adapter/accountV3Adapter.d.ts.map +1 -0
  79. package/dist/src/services/accountService/adapters/accountV3Adapter/accountV3Adapter.js +109 -19
  80. package/dist/src/services/accountService/adapters/accountV3Adapter/accountV3Adapter.js.map +1 -1
  81. package/dist/src/services/accountService/adapters/accountVaultsSubgraphAdapter/accountVaultsSubgraphAdapter.d.ts +1 -0
  82. package/dist/src/services/accountService/adapters/accountVaultsSubgraphAdapter/accountVaultsSubgraphAdapter.d.ts.map +1 -0
  83. package/dist/src/services/accountService/index.d.ts +1 -0
  84. package/dist/src/services/accountService/index.d.ts.map +1 -0
  85. package/dist/src/services/deploymentService/deploymentService.d.ts +1 -0
  86. package/dist/src/services/deploymentService/deploymentService.d.ts.map +1 -0
  87. package/dist/src/services/deploymentService/index.d.ts +1 -0
  88. package/dist/src/services/deploymentService/index.d.ts.map +1 -0
  89. package/dist/src/services/eulerLabelsService/eulerLabelsService.d.ts +2 -10
  90. package/dist/src/services/eulerLabelsService/eulerLabelsService.d.ts.map +1 -0
  91. package/dist/src/services/eulerLabelsService/eulerLabelsService.js +43 -53
  92. package/dist/src/services/eulerLabelsService/eulerLabelsService.js.map +1 -1
  93. package/dist/src/services/eulerLabelsService/index.d.ts +1 -0
  94. package/dist/src/services/eulerLabelsService/index.d.ts.map +1 -0
  95. package/dist/src/services/executionService/abis/eVaultAbi.d.ts +1 -0
  96. package/dist/src/services/executionService/abis/eVaultAbi.d.ts.map +1 -0
  97. package/dist/src/services/executionService/abis/ethereumVaultConnectorAbi.d.ts +1 -0
  98. package/dist/src/services/executionService/abis/ethereumVaultConnectorAbi.d.ts.map +1 -0
  99. package/dist/src/services/executionService/abis/permit2PermitAbi.d.ts +1 -0
  100. package/dist/src/services/executionService/abis/permit2PermitAbi.d.ts.map +1 -0
  101. package/dist/src/services/executionService/abis/swapVerifierAbi.d.ts +1 -0
  102. package/dist/src/services/executionService/abis/swapVerifierAbi.d.ts.map +1 -0
  103. package/dist/src/services/executionService/abis/swapperAbi.d.ts +1 -0
  104. package/dist/src/services/executionService/abis/swapperAbi.d.ts.map +1 -0
  105. package/dist/src/services/executionService/encode.d.ts +30 -0
  106. package/dist/src/services/executionService/encode.d.ts.map +1 -0
  107. package/dist/src/services/executionService/encode.js +841 -0
  108. package/dist/src/services/executionService/encode.js.map +1 -0
  109. package/dist/src/services/executionService/execute.d.ts +64 -0
  110. package/dist/src/services/executionService/execute.d.ts.map +1 -0
  111. package/dist/src/services/executionService/execute.js +181 -0
  112. package/dist/src/services/executionService/execute.js.map +1 -0
  113. package/dist/src/services/executionService/executionService.d.ts +192 -38
  114. package/dist/src/services/executionService/executionService.d.ts.map +1 -0
  115. package/dist/src/services/executionService/executionService.js +557 -864
  116. package/dist/src/services/executionService/executionService.js.map +1 -1
  117. package/dist/src/services/executionService/executionServiceTypes.d.ts +106 -9
  118. package/dist/src/services/executionService/executionServiceTypes.d.ts.map +1 -0
  119. package/dist/src/services/executionService/executionServiceTypes.js +6 -0
  120. package/dist/src/services/executionService/executionServiceTypes.js.map +1 -1
  121. package/dist/src/services/executionService/index.d.ts +6 -2
  122. package/dist/src/services/executionService/index.d.ts.map +1 -0
  123. package/dist/src/services/executionService/index.js +3 -1
  124. package/dist/src/services/executionService/index.js.map +1 -1
  125. package/dist/src/services/{simulationService/simulationService.d.ts → executionService/simulate.d.ts} +31 -37
  126. package/dist/src/services/executionService/simulate.d.ts.map +1 -0
  127. package/dist/src/services/executionService/simulate.js +531 -0
  128. package/dist/src/services/executionService/simulate.js.map +1 -0
  129. package/dist/src/services/feeFlowService/feeFlowService.d.ts +1 -0
  130. package/dist/src/services/feeFlowService/feeFlowService.d.ts.map +1 -0
  131. package/dist/src/services/feeFlowService/feeFlowServiceTypes.d.ts +1 -0
  132. package/dist/src/services/feeFlowService/feeFlowServiceTypes.d.ts.map +1 -0
  133. package/dist/src/services/feeFlowService/index.d.ts +1 -0
  134. package/dist/src/services/feeFlowService/index.d.ts.map +1 -0
  135. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/index.d.ts +1 -0
  136. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/index.d.ts.map +1 -0
  137. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.d.ts +1 -0
  138. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3Adapter.d.ts.map +1 -0
  139. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3AdapterTypes.d.ts +2 -1
  140. package/dist/src/services/intrinsicApyService/adapters/intrinsicApyV3Adapter/intrinsicApyV3AdapterTypes.d.ts.map +1 -0
  141. package/dist/src/services/intrinsicApyService/index.d.ts +1 -0
  142. package/dist/src/services/intrinsicApyService/index.d.ts.map +1 -0
  143. package/dist/src/services/intrinsicApyService/intrinsicApyService.d.ts +1 -0
  144. package/dist/src/services/intrinsicApyService/intrinsicApyService.d.ts.map +1 -0
  145. package/dist/src/services/oracleAdapterService/index.d.ts +1 -0
  146. package/dist/src/services/oracleAdapterService/index.d.ts.map +1 -0
  147. package/dist/src/services/oracleAdapterService/oracleAdapterService.d.ts +1 -0
  148. package/dist/src/services/oracleAdapterService/oracleAdapterService.d.ts.map +1 -0
  149. package/dist/src/services/portfolioService/index.d.ts +3 -0
  150. package/dist/src/services/portfolioService/index.d.ts.map +1 -0
  151. package/dist/src/services/portfolioService/index.js +2 -0
  152. package/dist/src/services/portfolioService/index.js.map +1 -0
  153. package/dist/src/services/portfolioService/portfolioService.d.ts +18 -0
  154. package/dist/src/services/portfolioService/portfolioService.d.ts.map +1 -0
  155. package/dist/src/services/portfolioService/portfolioService.js +21 -0
  156. package/dist/src/services/portfolioService/portfolioService.js.map +1 -0
  157. package/dist/src/services/priceService/backendClient.d.ts +1 -2
  158. package/dist/src/services/priceService/backendClient.d.ts.map +1 -0
  159. package/dist/src/services/priceService/backendClient.js.map +1 -1
  160. package/dist/src/services/priceService/index.d.ts +1 -0
  161. package/dist/src/services/priceService/index.d.ts.map +1 -0
  162. package/dist/src/services/priceService/priceService.d.ts +1 -0
  163. package/dist/src/services/priceService/priceService.d.ts.map +1 -0
  164. package/dist/src/services/priceService/utilsLensPriceAbi.d.ts +1 -0
  165. package/dist/src/services/priceService/utilsLensPriceAbi.d.ts.map +1 -0
  166. package/dist/src/services/providerService/index.d.ts +1 -0
  167. package/dist/src/services/providerService/index.d.ts.map +1 -0
  168. package/dist/src/services/providerService/providerService.d.ts +1 -0
  169. package/dist/src/services/providerService/providerService.d.ts.map +1 -0
  170. package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/index.d.ts +1 -0
  171. package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/index.d.ts.map +1 -0
  172. package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts +1 -0
  173. package/dist/src/services/rewardsService/adapters/rewardsDirectAdapter/rewardsDirectAdapter.d.ts.map +1 -0
  174. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/index.d.ts +1 -0
  175. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/index.d.ts.map +1 -0
  176. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.d.ts +1 -0
  177. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.d.ts.map +1 -0
  178. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js +26 -13
  179. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3Adapter.js.map +1 -1
  180. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts +11 -10
  181. package/dist/src/services/rewardsService/adapters/rewardsV3Adapter/rewardsV3AdapterTypes.d.ts.map +1 -0
  182. package/dist/src/services/rewardsService/index.d.ts +1 -0
  183. package/dist/src/services/rewardsService/index.d.ts.map +1 -0
  184. package/dist/src/services/rewardsService/rewardsService.d.ts +1 -0
  185. package/dist/src/services/rewardsService/rewardsService.d.ts.map +1 -0
  186. package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts +6 -5
  187. package/dist/src/services/rewardsService/rewardsServiceTypes.d.ts.map +1 -0
  188. package/dist/src/services/swapService/index.d.ts +2 -1
  189. package/dist/src/services/swapService/index.d.ts.map +1 -0
  190. package/dist/src/services/swapService/swapService.d.ts +34 -2
  191. package/dist/src/services/swapService/swapService.d.ts.map +1 -0
  192. package/dist/src/services/swapService/swapService.js +123 -4
  193. package/dist/src/services/swapService/swapService.js.map +1 -1
  194. package/dist/src/services/swapService/swapServiceTypes.d.ts +12 -0
  195. package/dist/src/services/swapService/swapServiceTypes.d.ts.map +1 -0
  196. package/dist/src/services/swapService/swapVerifierAbi.d.ts +1 -0
  197. package/dist/src/services/swapService/swapVerifierAbi.d.ts.map +1 -0
  198. package/dist/src/services/tokenlistService/index.d.ts +1 -0
  199. package/dist/src/services/tokenlistService/index.d.ts.map +1 -0
  200. package/dist/src/services/tokenlistService/tokenlistService.d.ts +1 -0
  201. package/dist/src/services/tokenlistService/tokenlistService.d.ts.map +1 -0
  202. package/dist/src/services/tokenlistService/tokenlistServiceTypes.d.ts +1 -0
  203. package/dist/src/services/tokenlistService/tokenlistServiceTypes.d.ts.map +1 -0
  204. package/dist/src/services/vaults/IVaultService.d.ts +1 -0
  205. package/dist/src/services/vaults/IVaultService.d.ts.map +1 -0
  206. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/abis/vaultLensAbi.d.ts +1 -0
  207. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/abis/vaultLensAbi.d.ts.map +1 -0
  208. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.d.ts +1 -0
  209. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultLensTypes.d.ts.map +1 -0
  210. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultOnchainAdapter.d.ts +1 -0
  211. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/eVaultOnchainAdapter.d.ts.map +1 -0
  212. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/vaultInfoConverter.d.ts +1 -0
  213. package/dist/src/services/vaults/eVaultService/adapters/eVaultOnchainAdapter/vaultInfoConverter.d.ts.map +1 -0
  214. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3Adapter.d.ts +2 -0
  215. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3Adapter.d.ts.map +1 -0
  216. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3Adapter.js +20 -3
  217. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3Adapter.js.map +1 -1
  218. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.d.ts +1 -0
  219. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.d.ts.map +1 -0
  220. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.js +30 -58
  221. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterConversions.js.map +1 -1
  222. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterTypes.d.ts +8 -0
  223. package/dist/src/services/vaults/eVaultService/adapters/eVaultV3Adapter/eVaultV3AdapterTypes.d.ts.map +1 -0
  224. package/dist/src/services/vaults/eVaultService/eVaultService.d.ts +1 -0
  225. package/dist/src/services/vaults/eVaultService/eVaultService.d.ts.map +1 -0
  226. package/dist/src/services/vaults/eVaultService/eVaultServiceConfig.d.ts +2 -1
  227. package/dist/src/services/vaults/eVaultService/eVaultServiceConfig.d.ts.map +1 -0
  228. package/dist/src/services/vaults/eVaultService/index.d.ts +1 -0
  229. package/dist/src/services/vaults/eVaultService/index.d.ts.map +1 -0
  230. package/dist/src/services/vaults/eulerEarnService/adapters/abis/eulerEarnVaultLensAbi.d.ts +1 -0
  231. package/dist/src/services/vaults/eulerEarnService/adapters/abis/eulerEarnVaultLensAbi.d.ts.map +1 -0
  232. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnInfoConverter.d.ts +1 -0
  233. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnInfoConverter.d.ts.map +1 -0
  234. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnLensTypes.d.ts +1 -0
  235. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnLensTypes.d.ts.map +1 -0
  236. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.d.ts +1 -0
  237. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnOnchainAdapter.d.ts.map +1 -0
  238. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnV3Adapter.d.ts +1 -0
  239. package/dist/src/services/vaults/eulerEarnService/adapters/eulerEarnV3Adapter.d.ts.map +1 -0
  240. package/dist/src/services/vaults/eulerEarnService/eulerEarnService.d.ts +1 -0
  241. package/dist/src/services/vaults/eulerEarnService/eulerEarnService.d.ts.map +1 -0
  242. package/dist/src/services/vaults/eulerEarnService/eulerEarnServiceConfig.d.ts +2 -1
  243. package/dist/src/services/vaults/eulerEarnService/eulerEarnServiceConfig.d.ts.map +1 -0
  244. package/dist/src/services/vaults/eulerEarnService/index.d.ts +1 -0
  245. package/dist/src/services/vaults/eulerEarnService/index.d.ts.map +1 -0
  246. package/dist/src/services/vaults/index.d.ts +1 -0
  247. package/dist/src/services/vaults/index.d.ts.map +1 -0
  248. package/dist/src/services/vaults/securitizeVaultService/adapters/abis/erc4626EvcCollateralSecuritizeAbi.d.ts +1 -0
  249. package/dist/src/services/vaults/securitizeVaultService/adapters/abis/erc4626EvcCollateralSecuritizeAbi.d.ts.map +1 -0
  250. package/dist/src/services/vaults/securitizeVaultService/adapters/abis/utilsLensAbi.d.ts +1 -0
  251. package/dist/src/services/vaults/securitizeVaultService/adapters/abis/utilsLensAbi.d.ts.map +1 -0
  252. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultInfoConverter.d.ts +1 -0
  253. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultInfoConverter.d.ts.map +1 -0
  254. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultLensTypes.d.ts +1 -0
  255. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultLensTypes.d.ts.map +1 -0
  256. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultOnchainAdapter.d.ts +1 -0
  257. package/dist/src/services/vaults/securitizeVaultService/adapters/securitizeVaultOnchainAdapter.d.ts.map +1 -0
  258. package/dist/src/services/vaults/securitizeVaultService/index.d.ts +1 -0
  259. package/dist/src/services/vaults/securitizeVaultService/index.d.ts.map +1 -0
  260. package/dist/src/services/vaults/securitizeVaultService/securitizeVaultService.d.ts +1 -0
  261. package/dist/src/services/vaults/securitizeVaultService/securitizeVaultService.d.ts.map +1 -0
  262. package/dist/src/services/vaults/vaultMetaService/adapters/IVaultTypeAdapter.d.ts +1 -0
  263. package/dist/src/services/vaults/vaultMetaService/adapters/IVaultTypeAdapter.d.ts.map +1 -0
  264. package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeSubgraphAdapter.d.ts +1 -0
  265. package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeSubgraphAdapter.d.ts.map +1 -0
  266. package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeV3Adapter.d.ts +2 -1
  267. package/dist/src/services/vaults/vaultMetaService/adapters/VaultTypeV3Adapter.d.ts.map +1 -0
  268. package/dist/src/services/vaults/vaultMetaService/index.d.ts +1 -0
  269. package/dist/src/services/vaults/vaultMetaService/index.d.ts.map +1 -0
  270. package/dist/src/services/vaults/vaultMetaService/vaultMetaService.d.ts +1 -0
  271. package/dist/src/services/vaults/vaultMetaService/vaultMetaService.d.ts.map +1 -0
  272. package/dist/src/services/walletService/adapters/walletOnchainAdapter.d.ts +1 -0
  273. package/dist/src/services/walletService/adapters/walletOnchainAdapter.d.ts.map +1 -0
  274. package/dist/src/services/walletService/index.d.ts +1 -0
  275. package/dist/src/services/walletService/index.d.ts.map +1 -0
  276. package/dist/src/services/walletService/walletService.d.ts +1 -0
  277. package/dist/src/services/walletService/walletService.d.ts.map +1 -0
  278. package/dist/src/utils/accountComputations.d.ts +59 -1
  279. package/dist/src/utils/accountComputations.d.ts.map +1 -0
  280. package/dist/src/utils/accountComputations.js +184 -3
  281. package/dist/src/utils/accountComputations.js.map +1 -1
  282. package/dist/src/utils/accountPositionClassification.d.ts +15 -0
  283. package/dist/src/utils/accountPositionClassification.d.ts.map +1 -0
  284. package/dist/src/utils/accountPositionClassification.js +27 -0
  285. package/dist/src/utils/accountPositionClassification.js.map +1 -0
  286. package/dist/src/utils/batch.d.ts +1 -0
  287. package/dist/src/utils/batch.d.ts.map +1 -0
  288. package/dist/src/utils/buildQuery.d.ts +1 -0
  289. package/dist/src/utils/buildQuery.d.ts.map +1 -0
  290. package/dist/src/utils/callBundler.d.ts +1 -0
  291. package/dist/src/utils/callBundler.d.ts.map +1 -0
  292. package/dist/src/utils/decodeSmartContractErrors.d.ts +1 -0
  293. package/dist/src/utils/decodeSmartContractErrors.d.ts.map +1 -0
  294. package/dist/src/utils/entityDiagnostics.d.ts +1 -0
  295. package/dist/src/utils/entityDiagnostics.d.ts.map +1 -0
  296. package/dist/src/utils/eulerErrorSelectors.d.ts +1 -0
  297. package/dist/src/utils/eulerErrorSelectors.d.ts.map +1 -0
  298. package/dist/src/utils/irm.d.ts +1 -0
  299. package/dist/src/utils/irm.d.ts.map +1 -0
  300. package/dist/src/utils/normalization.d.ts +1 -0
  301. package/dist/src/utils/normalization.d.ts.map +1 -0
  302. package/dist/src/utils/oracle.d.ts +1 -0
  303. package/dist/src/utils/oracle.d.ts.map +1 -0
  304. package/dist/src/utils/parsing.d.ts +1 -0
  305. package/dist/src/utils/parsing.d.ts.map +1 -0
  306. package/dist/src/utils/queryNames.d.ts +1 -0
  307. package/dist/src/utils/queryNames.d.ts.map +1 -0
  308. package/dist/src/utils/stateOverrides/accessList.d.ts +1 -0
  309. package/dist/src/utils/stateOverrides/accessList.d.ts.map +1 -0
  310. package/dist/src/utils/stateOverrides/approvalOverrides.d.ts +1 -0
  311. package/dist/src/utils/stateOverrides/approvalOverrides.d.ts.map +1 -0
  312. package/dist/src/utils/stateOverrides/balanceOverrides.d.ts +1 -0
  313. package/dist/src/utils/stateOverrides/balanceOverrides.d.ts.map +1 -0
  314. package/dist/src/utils/stateOverrides/getStateOverrides.d.ts +1 -0
  315. package/dist/src/utils/stateOverrides/getStateOverrides.d.ts.map +1 -0
  316. package/dist/src/utils/stateOverrides/index.d.ts +1 -0
  317. package/dist/src/utils/stateOverrides/index.d.ts.map +1 -0
  318. package/dist/src/utils/stateOverrides/mergeStateOverrides.d.ts +1 -0
  319. package/dist/src/utils/stateOverrides/mergeStateOverrides.d.ts.map +1 -0
  320. package/dist/src/utils/stateOverrides/types.d.ts +1 -0
  321. package/dist/src/utils/stateOverrides/types.d.ts.map +1 -0
  322. package/dist/src/utils/subAccounts.d.ts +14 -0
  323. package/dist/src/utils/subAccounts.d.ts.map +1 -0
  324. package/dist/src/utils/subAccounts.js +39 -3
  325. package/dist/src/utils/subAccounts.js.map +1 -1
  326. package/dist/src/utils/types.d.ts +1 -0
  327. package/dist/src/utils/types.d.ts.map +1 -0
  328. package/package.json +9 -4
  329. package/dist/src/services/simulationService/index.d.ts +0 -2
  330. package/dist/src/services/simulationService/index.js +0 -2
  331. package/dist/src/services/simulationService/index.js.map +0 -1
  332. package/dist/src/services/simulationService/simulationService.js +0 -497
  333. package/dist/src/services/simulationService/simulationService.js.map +0 -1
@@ -1,28 +1,120 @@
1
- import { encodeFunctionData, getAddress, maxUint256, zeroAddress, maxUint160, maxUint48, erc20Abi, decodeFunctionData, } from "viem";
1
+ import { decodeFunctionData, encodeFunctionData, erc20Abi, getAddress, maxUint256, maxUint160, } from "viem";
2
+ import { resolveBorrowCollateralPositions } from "../../utils/accountPositionClassification.js";
2
3
  import { ethereumVaultConnectorAbi } from "./abis/ethereumVaultConnectorAbi.js";
3
4
  import { eVaultAbi } from "./abis/eVaultAbi.js";
4
5
  import { permit2PermitAbi } from "./abis/permit2PermitAbi.js";
5
6
  import { swapperAbi } from "./abis/swapperAbi.js";
6
7
  import { swapVerifierAbi } from "./abis/swapVerifierAbi.js";
7
- import { PERMIT2_TYPES, } from "./executionServiceTypes.js";
8
- const PERMIT2_SIG_WINDOW = 60n * 60n;
8
+ import * as encodeHelpers from "./encode.js";
9
+ import { isEVCBatchOperation } from "./executionServiceTypes.js";
10
+ import { executeTransactionPlan, } from "./execute.js";
11
+ import { deriveStateOverrides, estimateGasForTransactionPlan, simulateTransactionPlan, } from "./simulate.js";
12
+ const TOKENS_REQUIRING_ZERO_APPROVAL_RESET = {
13
+ 1: [getAddress("0xdAC17F958D2ee523a2206206994597C13D831ec7")],
14
+ };
15
+ function requiresZeroApprovalReset(chainId, token) {
16
+ return (TOKENS_REQUIRING_ZERO_APPROVAL_RESET[chainId]?.some((resetToken) => resetToken === getAddress(token)) ?? false);
17
+ }
18
+ function isSavingsCollateral(collateral) {
19
+ return collateral?.source === "savings";
20
+ }
21
+ function isWalletCollateral(collateral) {
22
+ return !!collateral && !isSavingsCollateral(collateral);
23
+ }
24
+ function cloneBatchEntries(entries) {
25
+ return entries.map((entry) => "type" in entry && entry.type === "operation"
26
+ ? { type: "operation", name: entry.name, items: [...entry.items] }
27
+ : entry);
28
+ }
9
29
  const WAD = 10n ** 18n;
10
30
  // TODO explain how this service is coupled to the concrete abis of ERC4626, permit2 and EVK.
11
31
  // this is a helper service, not a generic one.
12
32
  export class ExecutionService {
13
33
  deploymentService;
14
- walletService;
15
34
  plugins = [];
16
- constructor(deploymentService, walletService) {
35
+ walletService;
36
+ providerService;
37
+ vaultMetaService;
38
+ priceService;
39
+ rewardsService;
40
+ intrinsicApyService;
41
+ eulerLabelsService;
42
+ constructor(deploymentService, walletService, providerService, vaultMetaService, priceService, rewardsService, intrinsicApyService, eulerLabelsService) {
17
43
  this.deploymentService = deploymentService;
18
44
  this.walletService = walletService;
45
+ this.providerService = providerService;
46
+ this.vaultMetaService = vaultMetaService;
47
+ this.priceService = priceService;
48
+ this.rewardsService = rewardsService;
49
+ this.intrinsicApyService = intrinsicApyService;
50
+ this.eulerLabelsService = eulerLabelsService;
19
51
  }
20
52
  setWalletService(walletService) {
21
53
  this.walletService = walletService;
22
54
  }
55
+ setProviderService(providerService) {
56
+ this.providerService = providerService;
57
+ }
58
+ setVaultMetaService(vaultMetaService) {
59
+ this.vaultMetaService = vaultMetaService;
60
+ }
61
+ setPriceService(priceService) {
62
+ this.priceService = priceService;
63
+ }
64
+ setRewardsService(rewardsService) {
65
+ this.rewardsService = rewardsService;
66
+ }
67
+ setIntrinsicApyService(intrinsicApyService) {
68
+ this.intrinsicApyService = intrinsicApyService;
69
+ }
70
+ setEulerLabelsService(eulerLabelsService) {
71
+ this.eulerLabelsService = eulerLabelsService;
72
+ }
23
73
  setPlugins(plugins) {
24
74
  this.plugins = plugins;
25
75
  }
76
+ /** Derive storage overrides needed to simulate the plan against the current account state. */
77
+ async deriveStateOverrides(chainId, account, transactionPlan, options) {
78
+ return deriveStateOverrides(this.getSimulationContext(), chainId, account, transactionPlan, options);
79
+ }
80
+ /** Simulate the full transaction plan, including approval resolution and plugin-aware batch execution. */
81
+ async simulateTransactionPlan(chainId, account, transactionPlan, options) {
82
+ return simulateTransactionPlan(this.getSimulationContext(), chainId, account, transactionPlan, options);
83
+ }
84
+ /** Estimate gas for the full transaction plan after applying the same simulation pipeline used for execution. */
85
+ async estimateGasForTransactionPlan(chainId, account, transactionPlan, options) {
86
+ return estimateGasForTransactionPlan(this.getSimulationContext(), chainId, account, transactionPlan, options);
87
+ }
88
+ /** Execute a transaction plan using caller-provided signing and send callbacks. */
89
+ async executeTransactionPlan(args) {
90
+ const { providerService } = this;
91
+ if (!providerService) {
92
+ throw new Error("ExecutionService.executeTransactionPlan requires a providerService. Pass it to the ExecutionService constructor or call setProviderService().");
93
+ }
94
+ const helperArgs = {
95
+ ...args,
96
+ executionService: this,
97
+ deploymentService: this.deploymentService,
98
+ providerService,
99
+ };
100
+ return executeTransactionPlan(helperArgs);
101
+ }
102
+ getSimulationContext() {
103
+ return {
104
+ deploymentService: this.deploymentService,
105
+ walletService: this.walletService,
106
+ providerService: this.providerService,
107
+ vaultMetaService: this.vaultMetaService,
108
+ priceService: this.priceService,
109
+ rewardsService: this.rewardsService,
110
+ intrinsicApyService: this.intrinsicApyService,
111
+ eulerLabelsService: this.eulerLabelsService,
112
+ describeBatch: (batch) => this.describeBatch(batch),
113
+ };
114
+ }
115
+ getCoreAddresses(chainId) {
116
+ return this.deploymentService.getDeployment(chainId).addresses.coreAddrs;
117
+ }
26
118
  /**
27
119
  * Encodes an array of EVC batch items into a single calldata hex for `EVC.batch()`.
28
120
  *
@@ -30,11 +122,7 @@ export class ExecutionService {
30
122
  * @returns Encoded calldata hex for the EVC batch call
31
123
  */
32
124
  encodeBatch(items) {
33
- return encodeFunctionData({
34
- abi: ethereumVaultConnectorAbi,
35
- functionName: "batch",
36
- args: [items],
37
- });
125
+ return encodeHelpers.encodeBatch(items);
38
126
  }
39
127
  /**
40
128
  * Encodes EVC batch items for depositing underlying assets into a vault (mints shares to receiver).
@@ -49,33 +137,9 @@ export class ExecutionService {
49
137
  * @param args.permit2 - Optional Permit2 message + signature; if set, prepends a permit2 permit call so transferFrom can be used
50
138
  * @returns Array of EVC batch items (optional permit2, optional enableCollateral, deposit)
51
139
  */
52
- encodeDeposit({ chainId, vault, amount, receiver, owner, enableCollateral, permit2, }) {
53
- const items = [];
54
- if (permit2) {
55
- const permit2Call = this.encodePermit2Call({
56
- chainId,
57
- owner,
58
- message: permit2.message,
59
- signature: permit2.signature,
60
- });
61
- items.push(permit2Call);
62
- }
63
- // Add enable collateral if flag is set
64
- if (enableCollateral) {
65
- items.push(this.encodeEnableCollateral(chainId, receiver, vault));
66
- }
67
- // Add deposit operation
68
- items.push({
69
- targetContract: vault,
70
- onBehalfOfAccount: owner,
71
- value: 0n,
72
- data: encodeFunctionData({
73
- abi: eVaultAbi,
74
- functionName: "deposit",
75
- args: [amount, receiver],
76
- }),
77
- });
78
- return items;
140
+ encodeDeposit({ chainId, ...args }) {
141
+ const { evc, permit2 } = this.getCoreAddresses(chainId);
142
+ return encodeHelpers.encodeDeposit(evc, permit2, { chainId, ...args });
79
143
  }
80
144
  /**
81
145
  * Encodes EVC batch items for minting vault shares by depositing underlying assets.
@@ -90,33 +154,9 @@ export class ExecutionService {
90
154
  * @param args.permit2 - Optional Permit2 message + signature for transferFrom
91
155
  * @returns Array of EVC batch items (optional permit2, optional enableCollateral, mint)
92
156
  */
93
- encodeMint({ chainId, vault, shares, receiver, owner, enableCollateral, permit2, }) {
94
- const items = [];
95
- if (permit2) {
96
- const permit2Call = this.encodePermit2Call({
97
- chainId,
98
- owner,
99
- message: permit2.message,
100
- signature: permit2.signature,
101
- });
102
- items.push(permit2Call);
103
- }
104
- // Add enable collateral if flag is set
105
- if (enableCollateral) {
106
- items.push(this.encodeEnableCollateral(chainId, receiver, vault));
107
- }
108
- // Add mint operation
109
- items.push({
110
- targetContract: vault,
111
- onBehalfOfAccount: owner,
112
- value: 0n,
113
- data: encodeFunctionData({
114
- abi: eVaultAbi,
115
- functionName: "mint",
116
- args: [shares, receiver],
117
- }),
118
- });
119
- return items;
157
+ encodeMint({ chainId, ...args }) {
158
+ const { evc, permit2 } = this.getCoreAddresses(chainId);
159
+ return encodeHelpers.encodeMint(evc, permit2, { chainId, ...args });
120
160
  }
121
161
  /**
122
162
  * Encodes EVC batch items for withdrawing underlying assets from a vault (burns shares).
@@ -130,24 +170,9 @@ export class ExecutionService {
130
170
  * @param args.disableCollateral - If true, appends disableCollateral( owner, vault ) via EVC before withdraw
131
171
  * @returns Array of EVC batch items (optional disableCollateral, withdraw)
132
172
  */
133
- encodeWithdraw({ chainId, vault, assets, receiver, owner, disableCollateral, }) {
134
- const items = [];
135
- // Add disable collateral if flag is set
136
- if (disableCollateral) {
137
- items.push(this.encodeDisableCollateral(chainId, owner, vault));
138
- }
139
- // Add withdraw operation
140
- items.push({
141
- targetContract: vault,
142
- onBehalfOfAccount: owner,
143
- value: 0n,
144
- data: encodeFunctionData({
145
- abi: eVaultAbi,
146
- functionName: "withdraw",
147
- args: [assets, receiver, owner],
148
- }),
149
- });
150
- return items;
173
+ encodeWithdraw({ chainId, ...args }) {
174
+ const { evc } = this.getCoreAddresses(chainId);
175
+ return encodeHelpers.encodeWithdraw(evc, { chainId, ...args });
151
176
  }
152
177
  /**
153
178
  * Encodes EVC batch items for redeeming vault shares for underlying assets.
@@ -161,24 +186,9 @@ export class ExecutionService {
161
186
  * @param args.disableCollateral - If true, prepends disableCollateral( owner, vault ) via EVC
162
187
  * @returns Array of EVC batch items (optional disableCollateral, redeem)
163
188
  */
164
- encodeRedeem({ chainId, vault, shares, receiver, owner, disableCollateral, }) {
165
- const items = [];
166
- // Add disable collateral if flag is set
167
- if (disableCollateral) {
168
- items.push(this.encodeDisableCollateral(chainId, owner, vault));
169
- }
170
- // Add redeem operation
171
- items.push({
172
- targetContract: vault,
173
- onBehalfOfAccount: owner,
174
- value: 0n,
175
- data: encodeFunctionData({
176
- abi: eVaultAbi,
177
- functionName: "redeem",
178
- args: [shares, receiver, owner],
179
- }),
180
- });
181
- return items;
189
+ encodeRedeem({ chainId, ...args }) {
190
+ const { evc } = this.getCoreAddresses(chainId);
191
+ return encodeHelpers.encodeRedeem(evc, { chainId, ...args });
182
192
  }
183
193
  /**
184
194
  * Encodes EVC batch items for borrowing from a liability vault, optionally depositing collateral in the same batch.
@@ -199,42 +209,8 @@ export class ExecutionService {
199
209
  * @returns Array of EVC batch items (optional deposit, optional disableController, optional enableController, borrow)
200
210
  */
201
211
  encodeBorrow(args) {
202
- const { chainId, vault, amount, owner, borrowAccount, receiver, enableController = true, currentController, collateralVault, collateralAmount, enableCollateral = true, collateralPermit2, } = args;
203
- const items = [];
204
- // Add collateral if provided
205
- if (collateralVault &&
206
- collateralAmount !== undefined &&
207
- collateralAmount > 0n) {
208
- const depositItems = this.encodeDeposit({
209
- chainId,
210
- vault: collateralVault,
211
- amount: collateralAmount,
212
- receiver: borrowAccount,
213
- enableCollateral,
214
- permit2: collateralPermit2,
215
- owner: owner,
216
- });
217
- items.push(...depositItems);
218
- }
219
- // Add disable controller if there's a different controller enabled
220
- if (currentController && currentController !== vault) {
221
- items.push(this.encodeDisableController(currentController, borrowAccount));
222
- }
223
- if (enableController) {
224
- items.push(this.encodeEnableController(chainId, borrowAccount, vault));
225
- }
226
- // Add borrow operation
227
- items.push({
228
- targetContract: vault,
229
- onBehalfOfAccount: borrowAccount,
230
- value: 0n,
231
- data: encodeFunctionData({
232
- abi: eVaultAbi,
233
- functionName: "borrow",
234
- args: [amount, receiver],
235
- }),
236
- });
237
- return items;
212
+ const { evc, permit2 } = this.getCoreAddresses(args.chainId);
213
+ return encodeHelpers.encodeBorrow(evc, permit2, args);
238
214
  }
239
215
  /**
240
216
  * Encodes EVC batch items for liquidating an undercollateralized account (repay debt, seize collateral).
@@ -251,28 +227,9 @@ export class ExecutionService {
251
227
  * @param args.enableCollateral - If true, enables collateral vault for liquidator sub-account after liquidate (default true)
252
228
  * @returns Array of EVC batch items (optional enableController, liquidate, optional enableCollateral)
253
229
  */
254
- encodeLiquidation({ chainId, vault, violator, collateral, repayAssets, minYieldBalance, liquidatorSubAccountAddress, enableCollateral = true, enableController = true, }) {
255
- const items = [];
256
- // Optionally enable controller for the liquidator account on the liability vault
257
- if (enableController) {
258
- items.push(this.encodeEnableController(chainId, liquidatorSubAccountAddress, vault));
259
- }
260
- // Perform the liquidation
261
- items.push({
262
- targetContract: vault,
263
- onBehalfOfAccount: liquidatorSubAccountAddress,
264
- value: 0n,
265
- data: encodeFunctionData({
266
- abi: eVaultAbi,
267
- functionName: "liquidate",
268
- args: [violator, collateral, repayAssets, minYieldBalance],
269
- }),
270
- });
271
- // Optionally enable collateral for the seized collateral vault on the liquidator account
272
- if (enableCollateral) {
273
- items.push(this.encodeEnableCollateral(chainId, liquidatorSubAccountAddress, collateral));
274
- }
275
- return items;
230
+ encodeLiquidation({ chainId, ...args }) {
231
+ const { evc } = this.getCoreAddresses(chainId);
232
+ return encodeHelpers.encodeLiquidation(evc, { chainId, ...args });
276
233
  }
277
234
  /**
278
235
  * Encodes EVC batch items for pulling debt from one sub-account to another on the same liability vault.
@@ -286,24 +243,9 @@ export class ExecutionService {
286
243
  * @param args.enableController - If true, enables vault as controller for `to` via EVC before pullDebt (default true)
287
244
  * @returns Array of EVC batch items (optional enableController, pullDebt)
288
245
  */
289
- encodePullDebt({ chainId, vault, amount, from, to, enableController = true, }) {
290
- const items = [];
291
- // Add enable controller if flag is set
292
- if (enableController) {
293
- items.push(this.encodeEnableController(chainId, to, vault));
294
- }
295
- // Add pullDebt operation
296
- items.push({
297
- targetContract: vault,
298
- onBehalfOfAccount: to,
299
- value: 0n,
300
- data: encodeFunctionData({
301
- abi: eVaultAbi,
302
- functionName: "pullDebt",
303
- args: [amount, from],
304
- }),
305
- });
306
- return items;
246
+ encodePullDebt({ chainId, ...args }) {
247
+ const { evc } = this.getCoreAddresses(chainId);
248
+ return encodeHelpers.encodePullDebt(evc, { chainId, ...args });
307
249
  }
308
250
  /**
309
251
  * Encodes EVC batch items for a multiply/leverage operation when liability and long asset differ (swap required).
@@ -327,77 +269,8 @@ export class ExecutionService {
327
269
  * @returns Array of EVC batch items
328
270
  */
329
271
  encodeMultiplyWithSwap(args) {
330
- const { chainId, collateralVault, collateralAmount, liabilityVault, liabilityAmount, longVault, owner, receiver, enableCollateral = true, enableCollateralLong = true, currentController, enableController = true, collateralPermit2, swapQuote, } = args;
331
- const items = [];
332
- // 1. Add permit2 for collateral if provided
333
- if (collateralPermit2) {
334
- const permit2Call = this.encodePermit2Call({
335
- chainId,
336
- owner,
337
- message: collateralPermit2.message,
338
- signature: collateralPermit2.signature,
339
- });
340
- items.push(permit2Call);
341
- }
342
- // 2. Deposit initial collateral if amount > 0
343
- if (collateralAmount > 0n) {
344
- // Enable collateral for collateral vault
345
- if (enableCollateral) {
346
- items.push(this.encodeEnableCollateral(chainId, receiver, collateralVault));
347
- }
348
- // Deposit collateral
349
- items.push({
350
- targetContract: collateralVault,
351
- onBehalfOfAccount: owner,
352
- value: 0n,
353
- data: encodeFunctionData({
354
- abi: eVaultAbi,
355
- functionName: "deposit",
356
- args: [collateralAmount, receiver],
357
- }),
358
- });
359
- }
360
- // 3. Disable current controller if there's a different one enabled
361
- if (currentController && currentController !== liabilityVault) {
362
- items.push(this.encodeDisableController(currentController, receiver));
363
- }
364
- // 4. Enable controller for liability vault
365
- if (enableController) {
366
- items.push(this.encodeEnableController(chainId, receiver, liabilityVault));
367
- }
368
- // 5. Borrow from liability vault to swapper
369
- items.push({
370
- targetContract: liabilityVault,
371
- onBehalfOfAccount: receiver,
372
- value: 0n,
373
- data: encodeFunctionData({
374
- abi: eVaultAbi,
375
- functionName: "borrow",
376
- args: [liabilityAmount, swapQuote.swap.swapperAddress],
377
- }),
378
- });
379
- // 6. Execute swap multicall
380
- items.push({
381
- targetContract: swapQuote.swap.swapperAddress,
382
- onBehalfOfAccount: receiver,
383
- value: 0n,
384
- data: swapQuote.swap.swapperData,
385
- });
386
- // 7. Verify swap and skim to long vault
387
- if (swapQuote.verify.type !== "skimMin") {
388
- throw new Error("Invalid swap quote type for multiply - must be skimMin");
389
- }
390
- items.push({
391
- targetContract: swapQuote.verify.verifierAddress,
392
- onBehalfOfAccount: receiver,
393
- value: 0n,
394
- data: swapQuote.verify.verifierData,
395
- });
396
- // 8. Enable collateral on long vault
397
- if (enableCollateralLong && collateralVault !== longVault) {
398
- items.push(this.encodeEnableCollateral(chainId, receiver, longVault));
399
- }
400
- return items;
272
+ const { evc, permit2 } = this.getCoreAddresses(args.chainId);
273
+ return encodeHelpers.encodeMultiplyWithSwap(evc, permit2, args);
401
274
  }
402
275
  /**
403
276
  * Encodes EVC batch items for a multiply/leverage operation when liability and long asset are the same (no swap).
@@ -420,71 +293,8 @@ export class ExecutionService {
420
293
  * @returns Array of EVC batch items
421
294
  */
422
295
  encodeMultiplySameAsset(args) {
423
- const { chainId, collateralVault, collateralAmount, liabilityVault, liabilityAmount, longVault, owner, receiver, enableCollateral = true, enableCollateralLong = true, enableController = true, currentController, collateralPermit2, } = args;
424
- const items = [];
425
- // 1. Add permit2 for collateral if provided
426
- if (collateralPermit2) {
427
- const permit2Call = this.encodePermit2Call({
428
- chainId,
429
- owner,
430
- message: collateralPermit2.message,
431
- signature: collateralPermit2.signature,
432
- });
433
- items.push(permit2Call);
434
- }
435
- // 2. Deposit initial collateral if amount > 0
436
- if (collateralAmount > 0n) {
437
- // Enable collateral for collateral vault
438
- if (enableCollateral) {
439
- items.push(this.encodeEnableCollateral(chainId, receiver, collateralVault));
440
- }
441
- // Deposit collateral
442
- items.push({
443
- targetContract: collateralVault,
444
- onBehalfOfAccount: owner,
445
- value: 0n,
446
- data: encodeFunctionData({
447
- abi: eVaultAbi,
448
- functionName: "deposit",
449
- args: [collateralAmount, receiver],
450
- }),
451
- });
452
- }
453
- // 3. Disable current controller if there's a different one enabled
454
- if (currentController && currentController !== liabilityVault) {
455
- items.push(this.encodeDisableController(currentController, receiver));
456
- }
457
- // 4. Enable controller for liability vault
458
- if (enableController) {
459
- items.push(this.encodeEnableController(chainId, receiver, liabilityVault));
460
- }
461
- // 5. Borrow from liability vault directly to long vault
462
- items.push({
463
- targetContract: liabilityVault,
464
- onBehalfOfAccount: receiver,
465
- value: 0n,
466
- data: encodeFunctionData({
467
- abi: eVaultAbi,
468
- functionName: "borrow",
469
- args: [liabilityAmount, longVault],
470
- }),
471
- });
472
- // 6. Skim borrowed assets to position
473
- items.push({
474
- targetContract: longVault,
475
- onBehalfOfAccount: receiver,
476
- value: 0n,
477
- data: encodeFunctionData({
478
- abi: eVaultAbi,
479
- functionName: "skim",
480
- args: [liabilityAmount, receiver],
481
- }),
482
- });
483
- // 7. Enable collateral on long vault
484
- if (enableCollateralLong) {
485
- items.push(this.encodeEnableCollateral(chainId, receiver, longVault));
486
- }
487
- return items;
296
+ const { evc, permit2 } = this.getCoreAddresses(args.chainId);
297
+ return encodeHelpers.encodeMultiplySameAsset(evc, permit2, args);
488
298
  }
489
299
  /**
490
300
  * Encodes EVC batch items for repaying debt using assets from the sender's wallet (transferFrom to vault then repay).
@@ -501,41 +311,16 @@ export class ExecutionService {
501
311
  * @returns Array of EVC batch items (optional permit2, repay, optional disableController)
502
312
  */
503
313
  encodeRepayFromWallet(args) {
504
- const { chainId, sender, liabilityVault, liabilityAmount, receiver, disableControllerOnMax = true, isMax = false, permit2, } = args;
505
- const items = [];
506
- if (permit2) {
507
- const permit2Call = this.encodePermit2Call({
508
- chainId,
509
- owner: sender,
510
- message: permit2.message,
511
- signature: permit2.signature,
512
- });
513
- items.push(permit2Call);
514
- }
515
- // Repay operation
516
- items.push({
517
- targetContract: liabilityVault,
518
- onBehalfOfAccount: sender,
519
- value: 0n,
520
- data: encodeFunctionData({
521
- abi: eVaultAbi,
522
- functionName: "repay",
523
- args: [isMax ? maxUint256 : liabilityAmount, receiver],
524
- }),
525
- });
526
- // Disable controller if needed (for max repay)
527
- // Sender must be allowed to act on behalf of receiver (sender is subaccount of receiver or is an operator)
528
- if (disableControllerOnMax && isMax) {
529
- items.push(this.encodeDisableController(liabilityVault, receiver));
530
- }
531
- return items;
314
+ const { permit2 } = this.getCoreAddresses(args.chainId);
315
+ return encodeHelpers.encodeRepayFromWallet(permit2, args);
532
316
  }
533
317
  /**
534
318
  * Encodes EVC batch items for repaying debt from a deposit (same-asset only).
535
- * Path 1: same asset and same vault → repayWithShares. Path 2: same asset, different vault → withdraw then repay/skim/repayWithShares as needed.
319
+ * Path 1: same asset and same vault → repayWithShares.
320
+ * Path 2: same asset, different vault → withdraw to liability vault, skim, then repayWithShares.
536
321
  *
537
322
  * @param args - Repay-from-deposit encoding arguments
538
- * @param args.chainId - Chain ID (used for EVC and optional permit2)
323
+ * @param args.chainId - Chain ID used for EVC controller calls
539
324
  * @param args.liabilityVault - Vault (liability) to repay debt to
540
325
  * @param args.liabilityAsset - Underlying asset address of the liability vault
541
326
  * @param args.liabilityAmount - Amount of liability to repay (maxUint256 with isMax for full repay)
@@ -545,37 +330,10 @@ export class ExecutionService {
545
330
  * @param args.fromAsset - Underlying asset of fromVault (must equal liabilityAsset)
546
331
  * @param args.disableControllerOnMax - When isMax, whether to disable controller for receiver (default true)
547
332
  * @param args.isMax - If true, repays full debt (amount used for withdraw sizing where applicable)
548
- * @param args.liabilityPermit2 - Optional Permit2 for liability asset when path uses transfer/repay
549
333
  * @returns Array of EVC batch items. Throws if fromAsset !== liabilityAsset.
550
334
  */
551
335
  encodeRepayFromDeposit(args) {
552
- const { chainId, liabilityVault, liabilityAsset, liabilityAmount, from, receiver, fromVault, fromAsset, disableControllerOnMax = true, isMax = false, liabilityPermit2, } = args;
553
- // PATH 1: Same asset, same vault - use repayWithShares
554
- if (fromAsset === liabilityAsset && fromVault === liabilityVault) {
555
- return this.encodeRepayWithSharesSameAssetAndVault({
556
- chainId,
557
- vault: liabilityVault,
558
- amount: liabilityAmount,
559
- receiver,
560
- from,
561
- disableController: isMax && disableControllerOnMax,
562
- });
563
- }
564
- // PATH 2: Same asset, different vault
565
- if (fromAsset === liabilityAsset) {
566
- return this.encodeRepayWithSharesSameAssetDifferentVault({
567
- chainId,
568
- fromVault,
569
- toVault: liabilityVault,
570
- amount: liabilityAmount,
571
- receiver,
572
- from,
573
- isMax,
574
- disableControllerOnMax,
575
- permit2: liabilityPermit2,
576
- });
577
- }
578
- throw new Error("encodeRepayFromDeposit only supports same-asset paths");
336
+ return encodeHelpers.encodeRepayFromDeposit(args);
579
337
  }
580
338
  /**
581
339
  * Encodes EVC batch items for repaying debt by swapping collateral (withdraw from vaultIn → swap → verify/repay debtMax).
@@ -590,50 +348,7 @@ export class ExecutionService {
590
348
  * @returns Array of EVC batch items (withdraw, swap, verify/repay, optional disableController)
591
349
  */
592
350
  encodeRepayWithSwap(args) {
593
- const { swapQuote, maxWithdraw, isMax = false, disableControllerOnMax = true, } = args;
594
- const items = [];
595
- // Determine withdraw amount (cap to available amount if provided)
596
- const withdrawAmount = maxWithdraw &&
597
- maxWithdraw < BigInt(swapQuote.amountInMax || swapQuote.amountIn)
598
- ? maxWithdraw
599
- : BigInt(swapQuote.amountInMax || swapQuote.amountIn);
600
- // 1. Withdraw collateral from vault to swapper
601
- items.push({
602
- targetContract: swapQuote.vaultIn,
603
- onBehalfOfAccount: swapQuote.accountIn,
604
- value: 0n,
605
- data: encodeFunctionData({
606
- abi: eVaultAbi,
607
- functionName: "withdraw",
608
- args: [
609
- withdrawAmount,
610
- swapQuote.swap.swapperAddress,
611
- swapQuote.accountIn,
612
- ],
613
- }),
614
- });
615
- // 2. Execute swap multicall
616
- items.push({
617
- targetContract: swapQuote.swap.swapperAddress,
618
- onBehalfOfAccount: swapQuote.accountIn,
619
- value: 0n,
620
- data: swapQuote.swap.swapperData,
621
- });
622
- // 3. Verify swap and repay (verifyDebtMax handles the repay)
623
- if (swapQuote.verify.type !== "debtMax") {
624
- throw new Error("Invalid swap quote type for repay - must be debtMax");
625
- }
626
- items.push({
627
- targetContract: swapQuote.verify.verifierAddress,
628
- onBehalfOfAccount: swapQuote.verify.account,
629
- value: 0n,
630
- data: swapQuote.verify.verifierData,
631
- });
632
- // 4. Disable controller if needed (for max repay)
633
- if (isMax && disableControllerOnMax) {
634
- items.push(this.encodeDisableController(swapQuote.receiver, swapQuote.accountOut));
635
- }
636
- return items;
351
+ return encodeHelpers.encodeRepayWithSwap(args);
637
352
  }
638
353
  /**
639
354
  * Encodes EVC batch items for depositing into a vault using tokens from the user's wallet, going through a swap.
@@ -648,42 +363,24 @@ export class ExecutionService {
648
363
  * @returns Array of EVC batch items (transferFromSender, swap, verify, optional enableCollateral)
649
364
  */
650
365
  encodeDepositWithSwapFromWallet(args) {
651
- const { chainId, swapQuote, amount, sender, enableCollateral = true, } = args;
652
- const items = [];
653
- // 1. Transfer tokens from sender's wallet to swapper via SwapVerifier.transferFromSender
654
- items.push({
655
- targetContract: swapQuote.verify.verifierAddress,
656
- onBehalfOfAccount: sender,
657
- value: 0n,
658
- data: encodeFunctionData({
659
- abi: swapVerifierAbi,
660
- functionName: "transferFromSender",
661
- args: [
662
- swapQuote.tokenIn.address,
663
- amount,
664
- swapQuote.swap.swapperAddress,
665
- ],
666
- }),
667
- });
668
- // 2. Execute swap multicall
669
- items.push({
670
- targetContract: swapQuote.swap.swapperAddress,
671
- onBehalfOfAccount: sender,
672
- value: 0n,
673
- data: swapQuote.swap.swapperData,
674
- });
675
- // 3. Verify swap
676
- items.push({
677
- targetContract: swapQuote.verify.verifierAddress,
678
- onBehalfOfAccount: swapQuote.accountOut || sender,
679
- value: 0n,
680
- data: swapQuote.verify.verifierData,
681
- });
682
- // 4. Enable collateral if needed
683
- if (enableCollateral && swapQuote.receiver) {
684
- items.push(this.encodeEnableCollateral(chainId, swapQuote.accountOut || sender, swapQuote.receiver));
685
- }
686
- return items;
366
+ const { evc } = this.getCoreAddresses(args.chainId);
367
+ return encodeHelpers.encodeDepositWithSwapFromWallet(evc, args);
368
+ }
369
+ /**
370
+ * Encodes EVC batch items for swapping a token from the sender's wallet into another token
371
+ * and transferring the output to `swapQuote.receiver`.
372
+ * The approval is given to SwapVerifier, then transferFromSender pulls tokens to Swapper,
373
+ * swap executes, and verifyAmountMinAndTransfer sends the output to the receiver wallet.
374
+ *
375
+ * @param args - Wallet-swap encoding arguments
376
+ * @param args.chainId - Chain ID (unused, kept for encode API symmetry)
377
+ * @param args.swapQuote - Quote with swap and verify steps (verify type transferMin)
378
+ * @param args.amount - Amount of input token to transfer from wallet to swapper
379
+ * @param args.sender - Wallet address providing the tokens (onBehalfOfAccount for transferFromSender)
380
+ * @returns Array of EVC batch items (transferFromSender, swap, verify)
381
+ */
382
+ encodeSwapFromWallet(args) {
383
+ return encodeHelpers.encodeSwapFromWallet(args);
687
384
  }
688
385
  /**
689
386
  * Encodes EVC batch items for swapping collateral: withdraw from vaultIn → swap → verify/skim to receiver; optional enable/disable collateral.
@@ -698,50 +395,8 @@ export class ExecutionService {
698
395
  * @returns Array of EVC batch items (withdraw, swap, verify/skim, optional disableCollateral, optional enableCollateral)
699
396
  */
700
397
  encodeSwapCollateral(args) {
701
- const { chainId, swapQuote, enableCollateral = true, disableCollateralOnMax = true, isMax = false, } = args;
702
- const items = [];
703
- // 1. Withdraw from source vault to swapper
704
- const withdrawAmount = BigInt(swapQuote.amountInMax || swapQuote.amountIn);
705
- items.push({
706
- targetContract: swapQuote.vaultIn,
707
- onBehalfOfAccount: swapQuote.accountIn,
708
- value: 0n,
709
- data: encodeFunctionData({
710
- abi: eVaultAbi,
711
- functionName: "withdraw",
712
- args: [
713
- withdrawAmount,
714
- swapQuote.swap.swapperAddress,
715
- swapQuote.accountIn,
716
- ],
717
- }),
718
- });
719
- // 2. Execute swap multicall
720
- items.push({
721
- targetContract: swapQuote.swap.swapperAddress,
722
- onBehalfOfAccount: swapQuote.accountIn,
723
- value: 0n,
724
- data: swapQuote.swap.swapperData,
725
- });
726
- // 3. Verify swap and skim
727
- if (swapQuote.verify.type !== "skimMin") {
728
- throw new Error("Invalid swap quote type for swap collateral - must be skimMin");
729
- }
730
- items.push({
731
- targetContract: swapQuote.verify.verifierAddress,
732
- onBehalfOfAccount: swapQuote.accountOut,
733
- value: 0n,
734
- data: swapQuote.verify.verifierData,
735
- });
736
- // 4. Disable collateral if needed (for max swap)
737
- if (isMax && disableCollateralOnMax) {
738
- items.push(this.encodeDisableCollateral(chainId, swapQuote.accountIn, swapQuote.vaultIn));
739
- }
740
- // 5. Enable collateral if needed
741
- if (enableCollateral) {
742
- items.push(this.encodeEnableCollateral(chainId, swapQuote.accountOut, swapQuote.receiver));
743
- }
744
- return items;
398
+ const { evc } = this.getCoreAddresses(args.chainId);
399
+ return encodeHelpers.encodeSwapCollateral(evc, args);
745
400
  }
746
401
  /**
747
402
  * Encodes EVC batch items for swapping debt: enableController → borrow from vaultIn → swap → verify/repay (debtMax).
@@ -755,46 +410,51 @@ export class ExecutionService {
755
410
  * @param args.isMax - If true, treats as full debt swap (can trigger disableControllerOnMax)
756
411
  * @returns Array of EVC batch items (optional enableController, borrow, swap, verify/repay, optional disableController)
757
412
  */
758
- encodeSwapDebt({ chainId, swapQuote, enableController = true, disableControllerOnMax = true, isMax = false, }) {
759
- const items = [];
760
- // Enable controller if needed
761
- if (enableController) {
762
- items.push(this.encodeEnableController(chainId, swapQuote.accountOut, swapQuote.vaultIn));
763
- }
764
- // Borrow from source vault
765
- const borrowAmount = BigInt(swapQuote.amountInMax);
766
- items.push({
767
- targetContract: swapQuote.vaultIn,
768
- onBehalfOfAccount: swapQuote.accountIn,
769
- value: 0n,
770
- data: encodeFunctionData({
771
- abi: eVaultAbi,
772
- functionName: "borrow",
773
- args: [borrowAmount, swapQuote.swap.swapperAddress],
774
- }),
775
- });
776
- // Execute swap multicall
777
- items.push({
778
- targetContract: swapQuote.swap.swapperAddress,
779
- onBehalfOfAccount: swapQuote.accountIn,
780
- value: 0n,
781
- data: swapQuote.swap.swapperData,
782
- });
783
- // Verify swap and skim
784
- if (swapQuote.verify.type !== "debtMax") {
785
- throw new Error("Invalid swap quote type for repay - must be debtMax");
786
- }
787
- items.push({
788
- targetContract: swapQuote.verify.verifierAddress,
789
- onBehalfOfAccount: swapQuote.accountOut,
790
- value: 0n,
791
- data: swapQuote.verify.verifierData,
792
- });
793
- // Disable controller if needed (for max swap)
794
- if (isMax && disableControllerOnMax) {
795
- items.push(this.encodeDisableController(swapQuote.receiver, swapQuote.accountIn));
796
- }
797
- return items;
413
+ encodeSwapDebt(args) {
414
+ const { evc } = this.getCoreAddresses(args.chainId);
415
+ return encodeHelpers.encodeSwapDebt(evc, args);
416
+ }
417
+ /**
418
+ * Encodes EVC batch items for migrating a supplied/collateral position between two same-asset vaults.
419
+ * Partial migration uses withdraw(amount, toVault, account) then skim(amount, account).
420
+ * Max migration uses redeem(maxShares || maxUint256, toVault, account) then skim(amount, account).
421
+ *
422
+ * @param args - Same-asset collateral migration encoding arguments
423
+ * @param args.chainId - Chain ID (used for EVC enable/disable collateral)
424
+ * @param args.fromVault - Source vault holding the supplied shares
425
+ * @param args.toVault - Destination vault with the same underlying asset
426
+ * @param args.amount - Asset amount expected to arrive at the destination vault and be skimmed
427
+ * @param args.account - Sub-account that owns the source shares and receives destination shares
428
+ * @param args.isMax - If true, redeems shares instead of withdrawing assets
429
+ * @param args.maxShares - Optional exact share amount for max migration; defaults to maxUint256
430
+ * @param args.enableCollateralTo - If true, enables the destination vault as collateral after skim
431
+ * @param args.disableCollateralFrom - If true, disables the source vault as collateral after enabling the destination
432
+ * @returns Array of EVC batch items
433
+ */
434
+ encodeMigrateSameAssetCollateral(args) {
435
+ const { evc } = this.getCoreAddresses(args.chainId);
436
+ return encodeHelpers.encodeMigrateSameAssetCollateral(evc, args);
437
+ }
438
+ /**
439
+ * Encodes EVC batch items for migrating a full debt position between two same-asset liability vaults.
440
+ * Flow: enable new controller → borrow with interest cushion to old vault → skim → repay old debt with shares
441
+ * → disable old controller → optionally sweep cushion to the new vault → optionally transfer remaining new-vault shares.
442
+ *
443
+ * @param args - Same-asset debt migration encoding arguments
444
+ * @param args.chainId - Chain ID (used for EVC enable controller)
445
+ * @param args.oldLiabilityVault - Existing debt vault to fully repay and disable
446
+ * @param args.newLiabilityVault - New same-asset debt vault to borrow from
447
+ * @param args.amount - Current debt amount before applying the 0.01% interest cushion
448
+ * @param args.account - Sub-account that owns the debt position
449
+ * @param args.enableController - If true, enables the new liability vault as controller first
450
+ * @param args.disableController - If true, disables the old liability vault after repayment
451
+ * @param args.sweepExcess - If true, redeems any old-vault cushion shares back to the new vault and skims them
452
+ * @param args.transferRemainingSharesTo - If set, transfers all new-vault shares from the sub-account to this address
453
+ * @returns Array of EVC batch items
454
+ */
455
+ encodeMigrateSameAssetDebt(args) {
456
+ const { evc } = this.getCoreAddresses(args.chainId);
457
+ return encodeHelpers.encodeMigrateSameAssetDebt(evc, args);
798
458
  }
799
459
  /**
800
460
  * Encodes EVC batch items for transferring vault shares between sub-accounts.
@@ -809,28 +469,9 @@ export class ExecutionService {
809
469
  * @param args.disableCollateralFrom - If true, prepends disableCollateral( from, vault ) via EVC before transfer
810
470
  * @returns Array of EVC batch items (optional disableCollateralFrom, transfer, optional enableCollateralTo)
811
471
  */
812
- encodeTransfer({ chainId, vault, to, amount, from, enableCollateralTo, disableCollateralFrom, }) {
813
- const items = [];
814
- // Add disable collateral from sender if flag is set
815
- if (disableCollateralFrom) {
816
- items.push(this.encodeDisableCollateral(chainId, from, vault));
817
- }
818
- // Add transfer operation
819
- items.push({
820
- targetContract: vault,
821
- onBehalfOfAccount: from,
822
- value: 0n,
823
- data: encodeFunctionData({
824
- abi: eVaultAbi,
825
- functionName: "transfer",
826
- args: [to, amount],
827
- }),
828
- });
829
- // Add enable collateral to receiver if flag is set
830
- if (enableCollateralTo) {
831
- items.push(this.encodeEnableCollateral(chainId, to, vault));
832
- }
833
- return items;
472
+ encodeTransfer({ chainId, ...args }) {
473
+ const { evc } = this.getCoreAddresses(chainId);
474
+ return encodeHelpers.encodeTransfer(evc, { chainId, ...args });
834
475
  }
835
476
  /**
836
477
  * Encodes a single EVC batch item that calls Permit2's `permit` with the given message and signature.
@@ -844,73 +485,23 @@ export class ExecutionService {
844
485
  * @returns Single EVC batch item (targetContract = Permit2, permit call)
845
486
  */
846
487
  encodePermit2Call(args) {
847
- const { chainId, owner, message, signature } = args;
848
- const deployment = this.deploymentService.getDeployment(chainId);
849
- const permit2 = deployment.addresses.coreAddrs.permit2;
850
- return {
851
- targetContract: permit2,
852
- onBehalfOfAccount: owner,
853
- value: 0n,
854
- data: encodeFunctionData({
855
- abi: permit2PermitAbi,
856
- functionName: "permit",
857
- args: [owner, message, signature],
858
- }),
859
- };
488
+ const { permit2 } = this.getCoreAddresses(args.chainId);
489
+ return encodeHelpers.encodePermit2Call(permit2, args);
860
490
  }
861
491
  encodeEnableCollateral(chainId, account, vault) {
862
- const deployment = this.deploymentService.getDeployment(chainId);
863
- const evc = deployment.addresses.coreAddrs.evc;
864
- return {
865
- targetContract: evc,
866
- onBehalfOfAccount: zeroAddress,
867
- value: 0n,
868
- data: encodeFunctionData({
869
- abi: ethereumVaultConnectorAbi,
870
- functionName: "enableCollateral",
871
- args: [account, vault],
872
- }),
873
- };
492
+ const { evc } = this.getCoreAddresses(chainId);
493
+ return encodeHelpers.encodeEnableCollateral(evc, account, vault);
874
494
  }
875
495
  encodeDisableCollateral(chainId, account, vault) {
876
- const deployment = this.deploymentService.getDeployment(chainId);
877
- const evc = deployment.addresses.coreAddrs.evc;
878
- return {
879
- targetContract: evc,
880
- onBehalfOfAccount: zeroAddress,
881
- value: 0n,
882
- data: encodeFunctionData({
883
- abi: ethereumVaultConnectorAbi,
884
- functionName: "disableCollateral",
885
- args: [account, vault],
886
- }),
887
- };
496
+ const { evc } = this.getCoreAddresses(chainId);
497
+ return encodeHelpers.encodeDisableCollateral(evc, account, vault);
888
498
  }
889
499
  encodeEnableController(chainId, account, vault) {
890
- const deployment = this.deploymentService.getDeployment(chainId);
891
- const evc = deployment.addresses.coreAddrs.evc;
892
- return {
893
- targetContract: evc,
894
- onBehalfOfAccount: zeroAddress,
895
- value: 0n,
896
- data: encodeFunctionData({
897
- abi: ethereumVaultConnectorAbi,
898
- functionName: "enableController",
899
- args: [account, vault],
900
- }),
901
- };
500
+ const { evc } = this.getCoreAddresses(chainId);
501
+ return encodeHelpers.encodeEnableController(evc, account, vault);
902
502
  }
903
503
  encodeDisableController(vault, account) {
904
- return {
905
- targetContract: vault,
906
- onBehalfOfAccount: account,
907
- value: 0n,
908
- data: encodeFunctionData({
909
- abi: eVaultAbi,
910
- functionName: "disableController",
911
- args: [],
912
- }),
913
- };
504
+ return encodeHelpers.encodeDisableController(vault, account);
914
505
  }
915
506
  /**
916
507
  * Builds EIP-712 typed data for a Permit2 PermitSingle signature (token approval for a spender).
@@ -927,46 +518,10 @@ export class ExecutionService {
927
518
  * @returns EIP-712 typed data (domain, types, primaryType, message) for signing
928
519
  */
929
520
  getPermit2TypedData(args) {
930
- const nowInSeconds = () => BigInt(Math.floor(Date.now() / 1000));
931
- const { chainId, token, amount, spender, nonce, sigDeadline, expiration } = args;
932
- const deployment = this.deploymentService.getDeployment(chainId);
933
- const permit2 = deployment.addresses.coreAddrs.permit2;
934
- const permitSingle = {
935
- details: {
936
- token,
937
- amount: amount > maxUint160 ? maxUint160 : amount,
938
- expiration: expiration ?? Number(maxUint48),
939
- nonce,
940
- },
941
- spender,
942
- sigDeadline: sigDeadline ?? nowInSeconds() + PERMIT2_SIG_WINDOW,
943
- };
944
- return {
945
- domain: {
946
- name: "Permit2",
947
- chainId,
948
- verifyingContract: permit2,
949
- },
950
- types: PERMIT2_TYPES,
951
- primaryType: "PermitSingle",
952
- message: permitSingle,
953
- };
521
+ const { permit2 } = this.getCoreAddresses(args.chainId);
522
+ return encodeHelpers.getPermit2TypedData(permit2, args);
954
523
  }
955
- /**
956
- * Decodes EVC batch items into human-readable function names and named arguments.
957
- * Tries known ABIs (EVC, eVault, Permit2, swapper, swapVerifier) to decode each item's data.
958
- *
959
- * @param batch - Array of EVC batch items (targetContract, onBehalfOfAccount, value, data) to decode
960
- * @param extraAbis - Optional extra ABIs to try first when decoding unknown batch items.
961
- * @returns Array of decoded items with targetContract, onBehalfOfAccount, functionName, and args (record of param name to value). Throws if any item cannot be decoded.
962
- * @example
963
- * const batchItems = executionService.encodeDeposit({ ... });
964
- * const described = executionService.describeBatch(batchItems);
965
- * console.log(described[0].functionName); // "deposit"
966
- * console.log(described[0].args); // { amount: 1000n, receiver: "0x..." }
967
- */
968
524
  describeBatch(batch, extraAbis) {
969
- const decodedBatchItems = [];
970
525
  const executionDecodeAbis = [
971
526
  ...(extraAbis ?? []),
972
527
  ethereumVaultConnectorAbi,
@@ -975,7 +530,7 @@ export class ExecutionService {
975
530
  swapperAbi,
976
531
  swapVerifierAbi,
977
532
  ];
978
- for (const item of batch) {
533
+ const decodeBatchItem = (item) => {
979
534
  let decoded = false;
980
535
  for (const abi of executionDecodeAbis) {
981
536
  try {
@@ -1000,14 +555,13 @@ export class ExecutionService {
1000
555
  }
1001
556
  });
1002
557
  }
1003
- decodedBatchItems.push({
558
+ decoded = true;
559
+ return {
1004
560
  targetContract: item.targetContract,
1005
561
  onBehalfOfAccount: item.onBehalfOfAccount,
1006
562
  functionName: decodedData.functionName,
1007
563
  args: namedArgs,
1008
- });
1009
- decoded = true;
1010
- break;
564
+ };
1011
565
  }
1012
566
  catch { }
1013
567
  }
@@ -1019,29 +573,35 @@ export class ExecutionService {
1019
573
  try {
1020
574
  const result = plugin.decodeBatchItem(item);
1021
575
  if (result) {
1022
- decodedBatchItems.push(result);
1023
576
  decoded = true;
1024
- break;
577
+ return result;
1025
578
  }
1026
579
  }
1027
580
  catch { }
1028
581
  }
1029
582
  }
1030
583
  if (!decoded) {
1031
- decodedBatchItems.push({
584
+ return {
1032
585
  targetContract: item.targetContract,
1033
586
  onBehalfOfAccount: item.onBehalfOfAccount,
1034
587
  functionName: "Unknown",
1035
588
  args: {},
1036
- });
589
+ };
1037
590
  }
1038
- }
1039
- return decodedBatchItems;
591
+ throw new Error("unreachable batch item decode state");
592
+ };
593
+ return batch.map((entry) => isEVCBatchOperation(entry)
594
+ ? {
595
+ type: "operation",
596
+ name: entry.name,
597
+ items: entry.items.map(decodeBatchItem),
598
+ }
599
+ : decodeBatchItem(entry));
1040
600
  }
1041
601
  /**
1042
602
  * Merges multiple transaction plans into a single plan.
1043
603
  * Required approvals for the same (token, owner, spender) are summed.
1044
- * Executable items are preserved in order; adjacent EVC batch items are concatenated.
604
+ * Executable items are preserved in order; adjacent EVC batches are concatenated without flattening operation groupings.
1045
605
  * Can be used to construct a transaction queue.
1046
606
  *
1047
607
  * @param plans - Array of transaction plans to merge
@@ -1067,19 +627,37 @@ export class ExecutionService {
1067
627
  else if (item.type === "evcBatch") {
1068
628
  const previous = executableItems[executableItems.length - 1];
1069
629
  if (previous?.type === "evcBatch") {
1070
- previous.items.push(...item.items);
630
+ previous.items.push(...cloneBatchEntries(item.items));
1071
631
  }
1072
632
  else {
1073
- executableItems.push({ type: "evcBatch", items: [...item.items] });
633
+ executableItems.push({
634
+ type: "evcBatch",
635
+ items: cloneBatchEntries(item.items),
636
+ });
1074
637
  }
1075
638
  }
1076
639
  else {
1077
- executableItems.push(item);
640
+ throw new Error("ExecutionService.mergePlans cannot merge contractCall plan items. Merge these plans manually to preserve call boundaries.");
1078
641
  }
1079
642
  }
1080
643
  }
1081
644
  return [...approvalByKey.values(), ...executableItems];
1082
645
  }
646
+ /**
647
+ * Appends a raw batch item to the last EVC batch in the plan, or creates one.
648
+ * Mutates and returns the provided plan.
649
+ */
650
+ addBatchItemToPlan(plan, item) {
651
+ for (let index = plan.length - 1; index >= 0; index--) {
652
+ const planItem = plan[index];
653
+ if (planItem?.type === "evcBatch") {
654
+ planItem.items.push(item);
655
+ return plan;
656
+ }
657
+ }
658
+ plan.push({ type: "evcBatch", items: [item] });
659
+ return plan;
660
+ }
1083
661
  /**
1084
662
  * Converts EVC batch items into a transaction plan.
1085
663
  * Returns a plan with a single evcBatch containing the given items (no required approvals).
@@ -1088,117 +666,50 @@ export class ExecutionService {
1088
666
  * @param items - EVC batch items to wrap in a plan
1089
667
  * @returns Transaction plan containing one evcBatch with the items
1090
668
  */
1091
- convertBatchItemsToPlan(items) {
669
+ convertBatchItemsToPlan(items, operationName) {
1092
670
  if (items.length === 0)
1093
671
  return [];
672
+ if (operationName) {
673
+ return [
674
+ {
675
+ type: "evcBatch",
676
+ items: [{ type: "operation", name: operationName, items }],
677
+ },
678
+ ];
679
+ }
1094
680
  return [{ type: "evcBatch", items }];
1095
681
  }
1096
- /**
1097
- * Encodes batch items for repaying with shares from the same asset and vault
1098
- */
1099
- encodeRepayWithSharesSameAssetAndVault({ chainId: _chainId, vault, amount, from, receiver, disableController, }) {
1100
- const items = [];
1101
- // Repay with shares
1102
- items.push({
1103
- targetContract: vault,
1104
- onBehalfOfAccount: from,
1105
- value: 0n,
1106
- data: encodeFunctionData({
1107
- abi: eVaultAbi,
1108
- functionName: "repayWithShares",
1109
- args: [amount, receiver],
1110
- }),
1111
- });
1112
- // Disable controller if needed (for max repay)
1113
- if (disableController) {
1114
- items.push(this.encodeDisableController(vault, receiver));
1115
- }
1116
- return items;
682
+ encodeTransferFromMax(vault, from, to) {
683
+ return encodeHelpers.encodeTransferFromMax(vault, from, to);
1117
684
  }
1118
685
  /**
1119
- * Encodes batch items for repaying with shares from same asset but different vault
686
+ * Appends post-full-repay cleanup calls owned by plan builders:
687
+ * disable each active collateral used by the repaid borrow, transfer those collateral shares to the owner,
688
+ * and, when a source deposit funded the repay, transfer any remaining source-vault shares to the owner.
1120
689
  */
1121
- encodeRepayWithSharesSameAssetDifferentVault({ chainId, fromVault, toVault, amount, // if isMax, this should be the total current debt
1122
- receiver, from, isMax, disableControllerOnMax, permit2, }) {
1123
- const items = [];
1124
- if (isMax) {
1125
- // if amount was max uint, skim and repay with shares would not revert if after withdraw funds were skimmed
1126
- // by other party
1127
- if (amount == maxUint256) {
1128
- throw new Error("Amount is maxUint256, cannot be used for max repay");
1129
- }
1130
- // For max repay: withdraw full debt amount +1 BPS to cover interest, then skim, then repayWithShares max
1131
- const amountWithExtra = (amount * 10001n) / 10000n;
1132
- if (amountWithExtra >= maxUint256) {
1133
- throw new Error("Amount with extra exceeds maxUint256");
1134
- }
1135
- // 1. Withdraw from collateral vault
1136
- items.push({
1137
- targetContract: fromVault,
1138
- onBehalfOfAccount: from,
1139
- value: 0n,
1140
- data: encodeFunctionData({
1141
- abi: eVaultAbi,
1142
- functionName: "withdraw",
1143
- args: [amountWithExtra, toVault, from],
1144
- }),
1145
- });
1146
- // 2. Skim exact withdrawal amount to liability vault
1147
- items.push({
1148
- targetContract: toVault,
1149
- onBehalfOfAccount: from,
1150
- value: 0n,
1151
- data: encodeFunctionData({
1152
- abi: eVaultAbi,
1153
- functionName: "skim",
1154
- args: [amountWithExtra, receiver],
1155
- }),
1156
- });
1157
- // 3. Repay with shares (max)
1158
- items.push({
1159
- targetContract: toVault,
1160
- onBehalfOfAccount: receiver,
1161
- value: 0n,
1162
- data: encodeFunctionData({
1163
- abi: eVaultAbi,
1164
- functionName: "repayWithShares",
1165
- // max is ok now, because skim deposited exact amount and it is the full debt,
1166
- // so pre-existing balance will not be consumed
1167
- args: [maxUint256, receiver],
1168
- }),
1169
- });
1170
- // 4. Disable controller if needed
1171
- if (disableControllerOnMax) {
1172
- items.push(this.encodeDisableController(toVault, receiver));
690
+ appendMaxRepayCleanup(args) {
691
+ const { account, liabilityPosition, receiver, batchItems, sourceAccount, sourceVault, } = args;
692
+ const receiverSubAccount = typeof account.getSubAccount === "function"
693
+ ? account.getSubAccount(receiver)
694
+ : undefined;
695
+ const activeCollaterals = receiverSubAccount
696
+ ? resolveBorrowCollateralPositions(receiverSubAccount, liabilityPosition)
697
+ : [];
698
+ const transferredPositions = new Set();
699
+ for (const collateral of activeCollaterals) {
700
+ batchItems.push(this.encodeDisableCollateral(account.chainId, receiver, collateral.vaultAddress));
701
+ if (getAddress(receiver) !== getAddress(account.owner)) {
702
+ batchItems.push(this.encodeTransferFromMax(collateral.vaultAddress, receiver, account.owner));
1173
703
  }
704
+ transferredPositions.add(`${getAddress(receiver)}:${getAddress(collateral.vaultAddress)}`);
1174
705
  }
1175
- else {
1176
- // For partial repay: withdraw, then repay exact amount
1177
- // 1. Withdraw from collateral vault
1178
- items.push({
1179
- targetContract: fromVault,
1180
- onBehalfOfAccount: from,
1181
- value: 0n,
1182
- data: encodeFunctionData({
1183
- abi: eVaultAbi,
1184
- functionName: "withdraw",
1185
- args: [amount, from, from],
1186
- }),
1187
- });
1188
- // 2. Repay exact amount
1189
- const repayItems = this.encodeRepayFromWallet({
1190
- chainId,
1191
- sender: from,
1192
- liabilityVault: toVault,
1193
- liabilityAmount: amount,
1194
- receiver,
1195
- disableControllerOnMax,
1196
- isMax,
1197
- permit2,
1198
- });
1199
- items.push(...repayItems);
706
+ if (sourceAccount && sourceVault) {
707
+ const sourcePositionKey = `${getAddress(sourceAccount)}:${getAddress(sourceVault)}`;
708
+ if (getAddress(sourceAccount) !== getAddress(account.owner) &&
709
+ !transferredPositions.has(sourcePositionKey)) {
710
+ batchItems.push(this.encodeTransferFromMax(sourceVault, sourceAccount, account.owner));
711
+ }
1200
712
  }
1201
- return items;
1202
713
  }
1203
714
  /**
1204
715
  * Resolves RequiredApproval items in a transaction plan by filling in each item's `resolved` field.
@@ -1237,6 +748,13 @@ export class ExecutionService {
1237
748
  args: [approvalSpender, approvalAmount],
1238
749
  }),
1239
750
  });
751
+ const addApproveWithOptionalReset = (approvalSpender, approvalAmount, currentAllowance) => {
752
+ if (currentAllowance > 0n &&
753
+ requiresZeroApprovalReset(chainId, token)) {
754
+ resolvedItems.push(makeApprove(approvalSpender, 0n));
755
+ }
756
+ resolvedItems.push(makeApprove(approvalSpender, approvalAmount));
757
+ };
1240
758
  const makePermit2 = (permit2Spender, permit2Amount) => ({
1241
759
  type: "permit2",
1242
760
  token,
@@ -1275,7 +793,7 @@ export class ExecutionService {
1275
793
  }
1276
794
  // If assetForPermit2 is insufficient, we need both approval and permit2 signature
1277
795
  if (!hasSufficientPermit2Allowance) {
1278
- resolvedItems.push(makeApprove(permit2, unlimitedApproval ? maxUint256 : amount));
796
+ addApproveWithOptionalReset(permit2, unlimitedApproval ? maxUint256 : amount, assetForPermit2);
1279
797
  resolvedItems.push(makePermit2(spender, unlimitedApproval ? maxUint160 : amount));
1280
798
  }
1281
799
  else {
@@ -1293,7 +811,7 @@ export class ExecutionService {
1293
811
  approval.resolved = [];
1294
812
  continue;
1295
813
  }
1296
- resolvedItems.push(makeApprove(spender, unlimitedApproval ? maxUint256 : amount));
814
+ addApproveWithOptionalReset(spender, unlimitedApproval ? maxUint256 : amount, assetForVault);
1297
815
  approval.resolved = resolvedItems;
1298
816
  }
1299
817
  }
@@ -1314,6 +832,9 @@ export class ExecutionService {
1314
832
  */
1315
833
  async resolveRequiredApprovals(args) {
1316
834
  const { plan, chainId, account, usePermit2 = true, unlimitedApproval = false, } = args;
835
+ if (!this.walletService) {
836
+ throw new Error("ExecutionService.resolveRequiredApprovals requires a walletService. Pass it to the ExecutionService constructor or call setWalletService().");
837
+ }
1317
838
  // Filter transaction plan for only RequiredApproval items
1318
839
  const requiredApprovals = plan.filter((item) => item.type === "requiredApproval");
1319
840
  // Transform RequiredApprovals into AssetWithSpenders
@@ -1378,10 +899,7 @@ export class ExecutionService {
1378
899
  enableCollateral: !isCollateralEnabled && enableCollateral,
1379
900
  // Permit2 is handled separately in the plan
1380
901
  });
1381
- plan.push({
1382
- type: "evcBatch",
1383
- items: batchItems,
1384
- });
902
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "deposit"));
1385
903
  return plan;
1386
904
  }
1387
905
  /**
@@ -1423,10 +941,7 @@ export class ExecutionService {
1423
941
  enableCollateral: !isCollateralEnabled && enableCollateral,
1424
942
  // Permit2 is handled separately in the plan
1425
943
  });
1426
- plan.push({
1427
- type: "evcBatch",
1428
- items: batchItems,
1429
- });
944
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "mint"));
1430
945
  return plan;
1431
946
  }
1432
947
  /**
@@ -1455,10 +970,7 @@ export class ExecutionService {
1455
970
  owner,
1456
971
  disableCollateral: disableCollateral && (!position || position.isCollateral),
1457
972
  });
1458
- plan.push({
1459
- type: "evcBatch",
1460
- items: batchItems,
1461
- });
973
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "withdraw"));
1462
974
  return plan;
1463
975
  }
1464
976
  /**
@@ -1488,10 +1000,7 @@ export class ExecutionService {
1488
1000
  owner,
1489
1001
  disableCollateral: disableCollateral && (!position || position.isCollateral),
1490
1002
  });
1491
- plan.push({
1492
- type: "evcBatch",
1493
- items: batchItems,
1494
- });
1003
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "redeem"));
1495
1004
  return plan;
1496
1005
  }
1497
1006
  /**
@@ -1513,6 +1022,12 @@ export class ExecutionService {
1513
1022
  planBorrow(args) {
1514
1023
  const { vault, amount, receiver, borrowAccount, account, collateral } = args;
1515
1024
  const plan = [];
1025
+ const savingsCollateral = isSavingsCollateral(collateral)
1026
+ ? collateral
1027
+ : undefined;
1028
+ const walletCollateral = isWalletCollateral(collateral)
1029
+ ? collateral
1030
+ : undefined;
1516
1031
  const enableCollateral = collateral && collateral.amount > 0n
1517
1032
  ? !(account?.isCollateralEnabled(borrowAccount, collateral.vault) ??
1518
1033
  false)
@@ -1521,15 +1036,15 @@ export class ExecutionService {
1521
1036
  // Default: controller is not enabled when account/sub-account is not available
1522
1037
  const currentController = account?.getCurrentController(borrowAccount);
1523
1038
  const enableController = !(account?.isControllerEnabled(borrowAccount, vault) ?? false);
1524
- if (collateral && collateral.amount > 0n) {
1039
+ if (walletCollateral && walletCollateral.amount > 0n) {
1525
1040
  // Approval is needed from the account owner (who owns the wallet tokens)
1526
1041
  // Add approval requirement (will be resolved later with Wallet data)
1527
1042
  plan.push({
1528
1043
  type: "requiredApproval",
1529
- token: collateral.asset,
1044
+ token: walletCollateral.asset,
1530
1045
  owner: account.owner,
1531
- spender: collateral.vault,
1532
- amount: collateral.amount,
1046
+ spender: walletCollateral.vault,
1047
+ amount: walletCollateral.amount,
1533
1048
  });
1534
1049
  }
1535
1050
  const batchItems = this.encodeBorrow({
@@ -1543,12 +1058,18 @@ export class ExecutionService {
1543
1058
  currentController: currentController || undefined,
1544
1059
  enableCollateral,
1545
1060
  collateralVault: collateral?.vault,
1546
- collateralAmount: collateral?.amount,
1547
- });
1548
- plan.push({
1549
- type: "evcBatch",
1550
- items: batchItems,
1061
+ collateralAmount: walletCollateral?.amount,
1062
+ collateralShareSource: savingsCollateral
1063
+ ? {
1064
+ from: savingsCollateral.from,
1065
+ shares: savingsCollateral.amount,
1066
+ disableCollateralFrom: savingsCollateral.disableCollateralFrom &&
1067
+ (account?.isCollateralEnabled(savingsCollateral.from, savingsCollateral.vault) ??
1068
+ false),
1069
+ }
1070
+ : undefined,
1551
1071
  });
1072
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "borrow"));
1552
1073
  return plan;
1553
1074
  }
1554
1075
  /**
@@ -1592,10 +1113,7 @@ export class ExecutionService {
1592
1113
  enableController,
1593
1114
  enableCollateral,
1594
1115
  });
1595
- plan.push({
1596
- type: "evcBatch",
1597
- items: batchItems,
1598
- });
1116
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "liquidation"));
1599
1117
  return plan;
1600
1118
  }
1601
1119
  /**
@@ -1607,10 +1125,11 @@ export class ExecutionService {
1607
1125
  * @param args.liabilityAmount - Amount of liability asset to repay (use maxUint256 for "repay all")
1608
1126
  * @param args.receiver - Sub-account address whose debt is being repaid
1609
1127
  * @param args.account - Account entity; used for chainId, owner, and position (to resolve liability asset)
1128
+ * @param args.cleanupOnMax - When true and liabilityAmount is maxUint256, the batch disables active collaterals on the repaid sub-account and transfers their shares to the owner account (default false)
1610
1129
  * @returns Array of transaction plan items (approval + EVC batch)
1611
1130
  */
1612
1131
  planRepayFromWallet(args) {
1613
- const { liabilityVault, liabilityAmount, receiver, account } = args;
1132
+ const { liabilityVault, liabilityAmount, receiver, account, cleanupOnMax = false, } = args;
1614
1133
  const plan = [];
1615
1134
  // Get position to determine asset
1616
1135
  const position = account?.getPosition(receiver, liabilityVault);
@@ -1625,6 +1144,7 @@ export class ExecutionService {
1625
1144
  spender: liabilityVault,
1626
1145
  amount: liabilityAmount,
1627
1146
  });
1147
+ const isMax = liabilityAmount === maxUint256;
1628
1148
  // Build EVC batch items
1629
1149
  const batchItems = this.encodeRepayFromWallet({
1630
1150
  chainId: account.chainId,
@@ -1633,18 +1153,28 @@ export class ExecutionService {
1633
1153
  liabilityAmount,
1634
1154
  receiver,
1635
1155
  disableControllerOnMax: true,
1636
- isMax: liabilityAmount === maxUint256,
1156
+ isMax,
1637
1157
  // Permit2 is handled separately in the plan
1638
1158
  });
1639
- plan.push({
1640
- type: "evcBatch",
1641
- items: batchItems,
1642
- });
1159
+ if (cleanupOnMax && isMax) {
1160
+ this.appendMaxRepayCleanup({
1161
+ account,
1162
+ liabilityPosition: position,
1163
+ receiver,
1164
+ batchItems,
1165
+ });
1166
+ }
1167
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "repayFromWallet"));
1643
1168
  return plan;
1644
1169
  }
1645
1170
  /**
1646
1171
  * Builds a transaction plan for repaying debt using assets from another vault deposit (same asset only).
1647
- * Use `maxUint256` for `liabilityAmount` to repay all available debt or up to the available deposit.
1172
+ * Use `maxUint256` for `liabilityAmount` to perform a full repay.
1173
+ * Full repay can opt into cleanup. For different-vault full repays, cleanup only redeems
1174
+ * liability-vault shares left from the repay cushion when the account snapshot shows no pre-existing liability-vault deposit;
1175
+ * otherwise those shares are preserved in the liability vault instead of being migrated to the source vault.
1176
+ * Cleanup also disables active collaterals on the repaid sub-account, transfers those collateral shares to the owner
1177
+ * account, and transfers any remaining source-vault shares from the source sub-account to the owner account.
1648
1178
  *
1649
1179
  * @param args - Repay-from-deposit plan arguments
1650
1180
  * @param args.liabilityVault - Address of the liability vault (debt is repaid to this vault)
@@ -1653,10 +1183,11 @@ export class ExecutionService {
1653
1183
  * @param args.fromVault - Vault to withdraw assets from (must be same underlying asset as liability for this plan)
1654
1184
  * @param args.fromAccount - Sub-account that holds the deposit in `fromVault`
1655
1185
  * @param args.account - Account entity; used for chainId, owner, and positions (to resolve assets and eligibility)
1656
- * @returns Array of transaction plan items (optional approval + EVC batch). Throws if asset differs between fromVault and liabilityVault; use planRepayWithSwap for cross-asset.
1186
+ * @param args.cleanupOnMax - Whether max repay should append repay-cushion, collateral, and source-share cleanup (default false)
1187
+ * @returns Array of transaction plan items (EVC batch only). Throws if asset differs between fromVault and liabilityVault; use planRepayWithSwap for cross-asset.
1657
1188
  */
1658
1189
  planRepayFromDeposit(args) {
1659
- const { liabilityVault, liabilityAmount, receiver, fromVault, fromAccount, account, } = args;
1190
+ const { liabilityVault, liabilityAmount, receiver, fromVault, fromAccount, account, cleanupOnMax = false, } = args;
1660
1191
  const plan = [];
1661
1192
  // Get positions
1662
1193
  const liabilityPosition = account?.getPosition(receiver, liabilityVault);
@@ -1668,40 +1199,65 @@ export class ExecutionService {
1668
1199
  }
1669
1200
  const liabilityAsset = liabilityPosition.asset;
1670
1201
  const fromAsset = fromPosition.asset;
1671
- // Check if approval is needed (only if different assets and we need to swap/withdraw)
1202
+ // Cross-asset repay requires a swap path; this planner only builds same-asset batches.
1672
1203
  if (fromAsset !== liabilityAsset) {
1673
1204
  // This path requires a swap, which is handled by planRepayWithSwap
1674
1205
  throw new Error("planRepayFromDeposit only supports same-asset paths. Use planRepayWithSwap for different assets.");
1675
1206
  }
1676
- // If same asset, different vault, we might need approval for the withdraw/repay path
1677
- if (fromVault !== liabilityVault) {
1678
- // Add approval requirement (will be resolved later with Wallet data)
1679
- plan.push({
1680
- type: "requiredApproval",
1681
- token: liabilityAsset,
1682
- owner: account.owner,
1683
- spender: liabilityVault,
1684
- amount: liabilityAmount,
1685
- });
1686
- }
1207
+ const isMax = liabilityAmount === maxUint256;
1208
+ const amount = isMax && fromVault !== liabilityVault
1209
+ ? liabilityPosition.borrowed
1210
+ : liabilityAmount;
1211
+ const hasPreExistingLiabilityDeposit = (liabilityPosition.assets ?? 0n) > 0n;
1687
1212
  // Build EVC batch items
1688
1213
  const batchItems = this.encodeRepayFromDeposit({
1689
1214
  chainId: account.chainId,
1690
1215
  liabilityVault,
1691
1216
  liabilityAsset,
1692
- liabilityAmount,
1693
- from: receiver,
1217
+ liabilityAmount: amount,
1218
+ from: fromAccount,
1694
1219
  receiver,
1695
1220
  fromVault,
1696
1221
  fromAsset,
1697
1222
  disableControllerOnMax: true,
1698
- isMax: liabilityAmount === maxUint256,
1223
+ isMax,
1699
1224
  // Permit2 is handled separately in the plan
1700
1225
  });
1701
- plan.push({
1702
- type: "evcBatch",
1703
- items: batchItems,
1704
- });
1226
+ if (cleanupOnMax && isMax) {
1227
+ if (fromVault !== liabilityVault && !hasPreExistingLiabilityDeposit) {
1228
+ // Sweep only the repay cushion. If liability shares existed before this batch,
1229
+ // redeem(max) would also migrate that unrelated deposit into the source vault.
1230
+ batchItems.push({
1231
+ targetContract: liabilityVault,
1232
+ onBehalfOfAccount: receiver,
1233
+ value: 0n,
1234
+ data: encodeFunctionData({
1235
+ abi: eVaultAbi,
1236
+ functionName: "redeem",
1237
+ args: [maxUint256, fromVault, receiver],
1238
+ }),
1239
+ });
1240
+ batchItems.push({
1241
+ targetContract: fromVault,
1242
+ onBehalfOfAccount: fromAccount,
1243
+ value: 0n,
1244
+ data: encodeFunctionData({
1245
+ abi: eVaultAbi,
1246
+ functionName: "skim",
1247
+ args: [maxUint256, fromAccount],
1248
+ }),
1249
+ });
1250
+ }
1251
+ this.appendMaxRepayCleanup({
1252
+ account,
1253
+ liabilityPosition,
1254
+ receiver,
1255
+ batchItems,
1256
+ sourceAccount: fromAccount,
1257
+ sourceVault: fromVault,
1258
+ });
1259
+ }
1260
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "repayFromDeposit"));
1705
1261
  return plan;
1706
1262
  }
1707
1263
  /**
@@ -1711,10 +1267,11 @@ export class ExecutionService {
1711
1267
  * @param args - Repay-with-swap plan arguments
1712
1268
  * @param args.swapQuote - Quote from swap service (e.g. fetchRepayQuotes); defines vaultIn, accountIn, accountOut, receiver, swap and verify steps
1713
1269
  * @param args.account - Account entity; used for chainId and positions (to compute isMax and maxWithdraw)
1270
+ * @param args.cleanupOnMax - When true and the quote repays the full debt, the batch disables active collaterals on the repaid sub-account, transfers their shares to the owner account, and transfers remaining source-vault shares to the owner account (default false)
1714
1271
  * @returns Array of transaction plan items (EVC batch: withdraw, swap, verify/repay). Throws if positions not found or liability is zero.
1715
1272
  */
1716
1273
  planRepayWithSwap(args) {
1717
- const { swapQuote, account } = args;
1274
+ const { swapQuote, account, cleanupOnMax = false } = args;
1718
1275
  const plan = [];
1719
1276
  const liabilityPosition = account?.getPosition(swapQuote.accountOut, swapQuote.receiver);
1720
1277
  const fromPosition = account?.getPosition(swapQuote.accountIn, swapQuote.vaultIn);
@@ -1733,10 +1290,17 @@ export class ExecutionService {
1733
1290
  isMax,
1734
1291
  disableControllerOnMax: true,
1735
1292
  });
1736
- plan.push({
1737
- type: "evcBatch",
1738
- items: batchItems,
1739
- });
1293
+ if (cleanupOnMax && isMax) {
1294
+ this.appendMaxRepayCleanup({
1295
+ account,
1296
+ liabilityPosition,
1297
+ receiver: swapQuote.accountOut,
1298
+ batchItems,
1299
+ sourceAccount: swapQuote.accountIn,
1300
+ sourceVault: swapQuote.vaultIn,
1301
+ });
1302
+ }
1303
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "repayWithSwap"));
1740
1304
  return plan;
1741
1305
  }
1742
1306
  /**
@@ -1778,10 +1342,37 @@ export class ExecutionService {
1778
1342
  sender: account.owner,
1779
1343
  enableCollateral: shouldEnableCollateral,
1780
1344
  });
1345
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "depositWithSwapFromWallet"));
1346
+ return plan;
1347
+ }
1348
+ /**
1349
+ * Builds a transaction plan for swapping a token from the sender's wallet into another
1350
+ * token and transferring the output to the quote receiver.
1351
+ *
1352
+ * @param args - Wallet-swap plan arguments
1353
+ * @param args.swapQuote - Quote from swap service; must use transferOutputToReceiver / transferMin verification
1354
+ * @param args.amount - Amount of input token to transfer from wallet
1355
+ * @param args.tokenIn - Input token address (for approval to SwapVerifier)
1356
+ * @param args.account - Account entity; used for chainId and owner
1357
+ * @returns Array of transaction plan items (approval to SwapVerifier + EVC batch)
1358
+ */
1359
+ planSwapFromWallet(args) {
1360
+ const { swapQuote, amount, tokenIn, account } = args;
1361
+ const plan = [];
1781
1362
  plan.push({
1782
- type: "evcBatch",
1783
- items: batchItems,
1363
+ type: "requiredApproval",
1364
+ token: tokenIn,
1365
+ owner: account.owner,
1366
+ spender: swapQuote.verify.verifierAddress,
1367
+ amount,
1784
1368
  });
1369
+ const batchItems = this.encodeSwapFromWallet({
1370
+ chainId: account.chainId,
1371
+ swapQuote,
1372
+ amount,
1373
+ sender: account.owner,
1374
+ });
1375
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "swapFromWallet"));
1785
1376
  return plan;
1786
1377
  }
1787
1378
  /**
@@ -1813,10 +1404,7 @@ export class ExecutionService {
1813
1404
  disableCollateralOnMax: true,
1814
1405
  isMax,
1815
1406
  });
1816
- plan.push({
1817
- type: "evcBatch",
1818
- items: batchItems,
1819
- });
1407
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "swapCollateral"));
1820
1408
  return plan;
1821
1409
  }
1822
1410
  /**
@@ -1844,10 +1432,103 @@ export class ExecutionService {
1844
1432
  disableControllerOnMax: true,
1845
1433
  isMax,
1846
1434
  });
1847
- plan.push({
1848
- type: "evcBatch",
1849
- items: batchItems,
1435
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "swapDebt"));
1436
+ return plan;
1437
+ }
1438
+ /**
1439
+ * Builds a transaction plan for migrating a supplied/collateral position between two same-asset vaults.
1440
+ * This is the no-swap path for moving shares from one vault to another vault with the same underlying asset.
1441
+ *
1442
+ * @param args - Same-asset collateral migration plan arguments
1443
+ * @param args.fromVault - Source vault holding the supplied shares
1444
+ * @param args.toVault - Destination vault with the same underlying asset
1445
+ * @param args.amount - Asset amount to withdraw/redeem and skim into the destination vault
1446
+ * @param args.positionAccount - Sub-account that owns the source shares and receives destination shares
1447
+ * @param args.fromAsset - Optional source underlying asset; defaults to the account position asset
1448
+ * @param args.toAsset - Destination underlying asset, used to verify this is a same-asset migration
1449
+ * @param args.isMax - If true, redeems shares instead of withdrawing assets
1450
+ * @param args.maxShares - Optional exact share amount for max migration
1451
+ * @param args.enableCollateralTo - Optional override for enabling destination collateral
1452
+ * @param args.disableCollateralFrom - Optional override for disabling source collateral
1453
+ * @returns Array of transaction plan items (EVC batch; no token approvals)
1454
+ */
1455
+ planMigrateSameAssetCollateral(args) {
1456
+ const { account, fromVault, toVault, amount, positionAccount, fromAsset, toAsset, isMax = false, maxShares, enableCollateralTo, disableCollateralFrom, } = args;
1457
+ const plan = [];
1458
+ const sourcePosition = account?.getPosition(positionAccount, fromVault);
1459
+ const resolvedFromAsset = fromAsset ?? sourcePosition?.asset;
1460
+ if (!resolvedFromAsset) {
1461
+ throw new Error(`Position not found. From vault: ${fromVault}, Account: ${positionAccount}. Source asset is required when position is not available.`);
1462
+ }
1463
+ if (getAddress(resolvedFromAsset) !== getAddress(toAsset)) {
1464
+ throw new Error("planMigrateSameAssetCollateral only supports same-asset vault migrations. Use planSwapCollateral for cross-asset migrations.");
1465
+ }
1466
+ const shouldEnableCollateralTo = enableCollateralTo ??
1467
+ !account.isCollateralEnabled(positionAccount, toVault);
1468
+ const shouldDisableCollateralFrom = disableCollateralFrom ??
1469
+ (isMax && account.isCollateralEnabled(positionAccount, fromVault));
1470
+ const batchItems = this.encodeMigrateSameAssetCollateral({
1471
+ chainId: account.chainId,
1472
+ fromVault,
1473
+ toVault,
1474
+ amount,
1475
+ account: positionAccount,
1476
+ isMax,
1477
+ maxShares: maxShares ?? (isMax ? sourcePosition?.shares : undefined),
1478
+ enableCollateralTo: shouldEnableCollateralTo,
1479
+ disableCollateralFrom: shouldDisableCollateralFrom,
1480
+ });
1481
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "migrateSameAssetCollateral"));
1482
+ return plan;
1483
+ }
1484
+ /**
1485
+ * Builds a transaction plan for migrating a full same-asset debt position from one liability vault to another.
1486
+ * This is the no-swap path for debt vault migration and repays the old vault with shares after borrowing
1487
+ * slightly more from the new vault to cover interest accrual.
1488
+ *
1489
+ * @param args - Same-asset debt migration plan arguments
1490
+ * @param args.oldLiabilityVault - Existing debt vault to fully repay and disable
1491
+ * @param args.newLiabilityVault - New same-asset debt vault to borrow from
1492
+ * @param args.liabilityAccount - Sub-account that owns the debt position
1493
+ * @param args.liabilityAmount - Current debt amount; defaults to the old-vault borrowed amount in account data
1494
+ * @param args.oldLiabilityAsset - Optional old liability asset; defaults to the old-vault account position asset
1495
+ * @param args.newLiabilityAsset - New liability underlying asset, used to verify this is a same-asset migration
1496
+ * @param args.sweepExcess - Whether to redeem and skim the migration cushion back into the new vault (default true)
1497
+ * @param args.transferRemainingSharesToOwner - Whether to transfer new-vault shares to the owner when liabilityAccount differs from owner (default true)
1498
+ * @returns Array of transaction plan items (EVC batch; no token approvals)
1499
+ */
1500
+ planMigrateSameAssetDebt(args) {
1501
+ const { account, oldLiabilityVault, newLiabilityVault, liabilityAccount, liabilityAmount, oldLiabilityAsset, newLiabilityAsset, sweepExcess = true, transferRemainingSharesToOwner = true, } = args;
1502
+ const plan = [];
1503
+ const oldPosition = account?.getPosition(liabilityAccount, oldLiabilityVault);
1504
+ const resolvedOldAsset = oldLiabilityAsset ?? oldPosition?.asset;
1505
+ if (!resolvedOldAsset) {
1506
+ throw new Error(`Position not found. Old liability vault: ${oldLiabilityVault}, Account: ${liabilityAccount}. Old liability asset is required when position is not available.`);
1507
+ }
1508
+ if (getAddress(resolvedOldAsset) !== getAddress(newLiabilityAsset)) {
1509
+ throw new Error("planMigrateSameAssetDebt only supports same-asset debt migrations. Use planSwapDebt for cross-asset migrations.");
1510
+ }
1511
+ const amount = liabilityAmount ?? oldPosition?.borrowed;
1512
+ if (!amount || amount <= 0n) {
1513
+ throw new Error(`Debt position not found or liability is 0. Old liability vault: ${oldLiabilityVault}, Account: ${liabilityAccount}`);
1514
+ }
1515
+ const enableController = !account.isControllerEnabled(liabilityAccount, newLiabilityVault);
1516
+ const transferRemainingSharesTo = transferRemainingSharesToOwner &&
1517
+ getAddress(liabilityAccount) !== getAddress(account.owner)
1518
+ ? account.owner
1519
+ : undefined;
1520
+ const batchItems = this.encodeMigrateSameAssetDebt({
1521
+ chainId: account.chainId,
1522
+ oldLiabilityVault,
1523
+ newLiabilityVault,
1524
+ amount,
1525
+ account: liabilityAccount,
1526
+ enableController,
1527
+ disableController: true,
1528
+ sweepExcess,
1529
+ transferRemainingSharesTo,
1850
1530
  });
1531
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "migrateSameAssetDebt"));
1851
1532
  return plan;
1852
1533
  }
1853
1534
  /**
@@ -1878,10 +1559,7 @@ export class ExecutionService {
1878
1559
  disableCollateralFrom: disableCollateralFrom &&
1879
1560
  (account?.isCollateralEnabled(from, vault) ?? false),
1880
1561
  });
1881
- plan.push({
1882
- type: "evcBatch",
1883
- items: batchItems,
1884
- });
1562
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "transfer"));
1885
1563
  return plan;
1886
1564
  }
1887
1565
  /**
@@ -1908,10 +1586,7 @@ export class ExecutionService {
1908
1586
  to,
1909
1587
  enableController,
1910
1588
  });
1911
- plan.push({
1912
- type: "evcBatch",
1913
- items: batchItems,
1914
- });
1589
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "pullDebt"));
1915
1590
  return plan;
1916
1591
  }
1917
1592
  /**
@@ -1927,10 +1602,10 @@ export class ExecutionService {
1927
1602
  * @returns Array of transaction plan items (optional approval + EVC batch). Throws if swapQuote.accountIn !== swapQuote.accountOut.
1928
1603
  */
1929
1604
  planMultiplyWithSwap(args) {
1930
- const { collateralVault, collateralAmount, collateralAsset, account, swapQuote, } = args;
1605
+ const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, account, swapQuote, } = args;
1931
1606
  const plan = [];
1932
1607
  // 1. Check if collateral approval is needed (only if depositing collateral)
1933
- if (collateralAmount > 0n) {
1608
+ if (!collateralShareSource && collateralAmount > 0n) {
1934
1609
  // Add approval requirement (will be resolved later with Wallet data)
1935
1610
  plan.push({
1936
1611
  type: "requiredApproval",
@@ -1948,8 +1623,19 @@ export class ExecutionService {
1948
1623
  const longVault = swapQuote.receiver;
1949
1624
  const liabilityAmount = BigInt(swapQuote.amountIn);
1950
1625
  // 2. Determine if collateral needs to be enabled
1951
- const enableCollateral = collateralAmount > 0n &&
1626
+ const hasCollateralInput = collateralShareSource
1627
+ ? collateralShareSource.shares > 0n
1628
+ : collateralAmount > 0n;
1629
+ const enableCollateral = hasCollateralInput &&
1952
1630
  !(account?.isCollateralEnabled(receiver, collateralVault) ?? false);
1631
+ const resolvedCollateralShareSource = collateralShareSource
1632
+ ? {
1633
+ ...collateralShareSource,
1634
+ disableCollateralFrom: collateralShareSource.disableCollateralFrom &&
1635
+ (account?.isCollateralEnabled(collateralShareSource.from, collateralVault) ??
1636
+ false),
1637
+ }
1638
+ : undefined;
1953
1639
  // 3. Determine if controller needs to be enabled
1954
1640
  const enableController = !(account?.isControllerEnabled(receiver, liabilityVault) ?? false);
1955
1641
  // 4. Get current controller (may need to disable if different)
@@ -1967,13 +1653,11 @@ export class ExecutionService {
1967
1653
  enableCollateral,
1968
1654
  currentController: currentController || undefined,
1969
1655
  enableController,
1656
+ collateralShareSource: resolvedCollateralShareSource,
1970
1657
  swapQuote,
1971
1658
  // Permit2 is handled separately in the plan
1972
1659
  });
1973
- plan.push({
1974
- type: "evcBatch",
1975
- items: batchItems,
1976
- });
1660
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplyWithSwap"));
1977
1661
  return plan;
1978
1662
  }
1979
1663
  /**
@@ -1992,10 +1676,10 @@ export class ExecutionService {
1992
1676
  * @returns Array of transaction plan items (optional approval + EVC batch)
1993
1677
  */
1994
1678
  planMultiplySameAsset(args) {
1995
- const { collateralVault, collateralAmount, collateralAsset, liabilityVault, liabilityAmount, longVault, receiver, account, } = args;
1679
+ const { collateralVault, collateralAmount, collateralAsset, collateralShareSource, liabilityVault, liabilityAmount, longVault, receiver, account, } = args;
1996
1680
  const plan = [];
1997
1681
  // 1. Check if collateral approval is needed (only if depositing collateral)
1998
- if (collateralAmount > 0n) {
1682
+ if (!collateralShareSource && collateralAmount > 0n) {
1999
1683
  // Add approval requirement (will be resolved later with Wallet data)
2000
1684
  plan.push({
2001
1685
  type: "requiredApproval",
@@ -2006,8 +1690,19 @@ export class ExecutionService {
2006
1690
  });
2007
1691
  }
2008
1692
  // 2. Determine if collateral needs to be enabled
2009
- const enableCollateral = collateralAmount > 0n &&
1693
+ const hasCollateralInput = collateralShareSource
1694
+ ? collateralShareSource.shares > 0n
1695
+ : collateralAmount > 0n;
1696
+ const enableCollateral = hasCollateralInput &&
2010
1697
  !(account?.isCollateralEnabled(receiver, collateralVault) ?? false);
1698
+ const resolvedCollateralShareSource = collateralShareSource
1699
+ ? {
1700
+ ...collateralShareSource,
1701
+ disableCollateralFrom: collateralShareSource.disableCollateralFrom &&
1702
+ (account?.isCollateralEnabled(collateralShareSource.from, collateralVault) ??
1703
+ false),
1704
+ }
1705
+ : undefined;
2011
1706
  // 3. Determine if controller needs to be enabled
2012
1707
  const enableController = !(account?.isControllerEnabled(receiver, liabilityVault) ?? false);
2013
1708
  // 4. Get current controller (may need to disable if different)
@@ -2025,12 +1720,10 @@ export class ExecutionService {
2025
1720
  enableCollateral,
2026
1721
  currentController: currentController || undefined,
2027
1722
  enableController,
1723
+ collateralShareSource: resolvedCollateralShareSource,
2028
1724
  // Permit2 is handled separately in the plan
2029
1725
  });
2030
- plan.push({
2031
- type: "evcBatch",
2032
- items: batchItems,
2033
- });
1726
+ plan.push(...this.convertBatchItemsToPlan(batchItems, "multiplySameAsset"));
2034
1727
  return plan;
2035
1728
  }
2036
1729
  }