@humanode-hyperlane/rebalancer 0.0.0-stage → 27.2.2

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 (439) hide show
  1. package/LICENSE.md +193 -0
  2. package/README.md +297 -2
  3. package/dist/bridges/LiFiBridge.d.ts +93 -0
  4. package/dist/bridges/LiFiBridge.d.ts.map +1 -0
  5. package/dist/bridges/LiFiBridge.js +527 -0
  6. package/dist/bridges/LiFiBridge.js.map +1 -0
  7. package/dist/bridges/LiFiBridge.test.d.ts +2 -0
  8. package/dist/bridges/LiFiBridge.test.d.ts.map +1 -0
  9. package/dist/bridges/LiFiBridge.test.js +504 -0
  10. package/dist/bridges/LiFiBridge.test.js.map +1 -0
  11. package/dist/config/RebalancerConfig.d.ts +20 -0
  12. package/dist/config/RebalancerConfig.d.ts.map +1 -0
  13. package/dist/config/RebalancerConfig.js +35 -0
  14. package/dist/config/RebalancerConfig.js.map +1 -0
  15. package/dist/config/RebalancerConfig.test.d.ts +2 -0
  16. package/dist/config/RebalancerConfig.test.d.ts.map +1 -0
  17. package/dist/config/RebalancerConfig.test.js +798 -0
  18. package/dist/config/RebalancerConfig.test.js.map +1 -0
  19. package/dist/config/types.d.ts +3008 -0
  20. package/dist/config/types.d.ts.map +1 -0
  21. package/dist/config/types.js +451 -0
  22. package/dist/config/types.js.map +1 -0
  23. package/dist/core/InventoryRebalancer.d.ts +201 -0
  24. package/dist/core/InventoryRebalancer.d.ts.map +1 -0
  25. package/dist/core/InventoryRebalancer.js +994 -0
  26. package/dist/core/InventoryRebalancer.js.map +1 -0
  27. package/dist/core/InventoryRebalancer.test.d.ts +2 -0
  28. package/dist/core/InventoryRebalancer.test.d.ts.map +1 -0
  29. package/dist/core/InventoryRebalancer.test.js +1511 -0
  30. package/dist/core/InventoryRebalancer.test.js.map +1 -0
  31. package/dist/core/Rebalancer.d.ts +37 -0
  32. package/dist/core/Rebalancer.d.ts.map +1 -0
  33. package/dist/core/Rebalancer.js +433 -0
  34. package/dist/core/Rebalancer.js.map +1 -0
  35. package/dist/core/Rebalancer.test.d.ts +2 -0
  36. package/dist/core/Rebalancer.test.d.ts.map +1 -0
  37. package/dist/core/Rebalancer.test.js +424 -0
  38. package/dist/core/Rebalancer.test.js.map +1 -0
  39. package/dist/core/RebalancerOrchestrator.d.ts +56 -0
  40. package/dist/core/RebalancerOrchestrator.d.ts.map +1 -0
  41. package/dist/core/RebalancerOrchestrator.js +154 -0
  42. package/dist/core/RebalancerOrchestrator.js.map +1 -0
  43. package/dist/core/RebalancerOrchestrator.test.d.ts +2 -0
  44. package/dist/core/RebalancerOrchestrator.test.d.ts.map +1 -0
  45. package/dist/core/RebalancerOrchestrator.test.js +721 -0
  46. package/dist/core/RebalancerOrchestrator.test.js.map +1 -0
  47. package/dist/core/RebalancerService.d.ts +127 -0
  48. package/dist/core/RebalancerService.d.ts.map +1 -0
  49. package/dist/core/RebalancerService.js +270 -0
  50. package/dist/core/RebalancerService.js.map +1 -0
  51. package/dist/core/RebalancerService.test.d.ts +2 -0
  52. package/dist/core/RebalancerService.test.d.ts.map +1 -0
  53. package/dist/core/RebalancerService.test.js +777 -0
  54. package/dist/core/RebalancerService.test.js.map +1 -0
  55. package/dist/e2e/collateral-deficit.e2e-test.d.ts +2 -0
  56. package/dist/e2e/collateral-deficit.e2e-test.d.ts.map +1 -0
  57. package/dist/e2e/collateral-deficit.e2e-test.js +227 -0
  58. package/dist/e2e/collateral-deficit.e2e-test.js.map +1 -0
  59. package/dist/e2e/composite.e2e-test.d.ts +2 -0
  60. package/dist/e2e/composite.e2e-test.d.ts.map +1 -0
  61. package/dist/e2e/composite.e2e-test.js +666 -0
  62. package/dist/e2e/composite.e2e-test.js.map +1 -0
  63. package/dist/e2e/fixtures/routes.d.ts +89 -0
  64. package/dist/e2e/fixtures/routes.d.ts.map +1 -0
  65. package/dist/e2e/fixtures/routes.js +420 -0
  66. package/dist/e2e/fixtures/routes.js.map +1 -0
  67. package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts +38 -0
  68. package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts.map +1 -0
  69. package/dist/e2e/harness/BaseLocalDeploymentManager.js +144 -0
  70. package/dist/e2e/harness/BaseLocalDeploymentManager.js.map +1 -0
  71. package/dist/e2e/harness/BridgeSetup.d.ts +11 -0
  72. package/dist/e2e/harness/BridgeSetup.d.ts.map +1 -0
  73. package/dist/e2e/harness/BridgeSetup.js +50 -0
  74. package/dist/e2e/harness/BridgeSetup.js.map +1 -0
  75. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts +13 -0
  76. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts.map +1 -0
  77. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js +105 -0
  78. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js.map +1 -0
  79. package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts +11 -0
  80. package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts.map +1 -0
  81. package/dist/e2e/harness/Erc20LocalDeploymentManager.js +105 -0
  82. package/dist/e2e/harness/Erc20LocalDeploymentManager.js.map +1 -0
  83. package/dist/e2e/harness/ForkIndexer.d.ts +23 -0
  84. package/dist/e2e/harness/ForkIndexer.d.ts.map +1 -0
  85. package/dist/e2e/harness/ForkIndexer.js +127 -0
  86. package/dist/e2e/harness/ForkIndexer.js.map +1 -0
  87. package/dist/e2e/harness/ForkIndexer.test.d.ts +2 -0
  88. package/dist/e2e/harness/ForkIndexer.test.d.ts.map +1 -0
  89. package/dist/e2e/harness/ForkIndexer.test.js +257 -0
  90. package/dist/e2e/harness/ForkIndexer.test.js.map +1 -0
  91. package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts +21 -0
  92. package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts.map +1 -0
  93. package/dist/e2e/harness/MixedLocalDeploymentManager.js +115 -0
  94. package/dist/e2e/harness/MixedLocalDeploymentManager.js.map +1 -0
  95. package/dist/e2e/harness/MockExplorerClient.d.ts +23 -0
  96. package/dist/e2e/harness/MockExplorerClient.d.ts.map +1 -0
  97. package/dist/e2e/harness/MockExplorerClient.js +57 -0
  98. package/dist/e2e/harness/MockExplorerClient.js.map +1 -0
  99. package/dist/e2e/harness/MockExternalBridge.d.ts +32 -0
  100. package/dist/e2e/harness/MockExternalBridge.d.ts.map +1 -0
  101. package/dist/e2e/harness/MockExternalBridge.js +247 -0
  102. package/dist/e2e/harness/MockExternalBridge.js.map +1 -0
  103. package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts +13 -0
  104. package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts.map +1 -0
  105. package/dist/e2e/harness/NativeLocalDeploymentManager.js +91 -0
  106. package/dist/e2e/harness/NativeLocalDeploymentManager.js.map +1 -0
  107. package/dist/e2e/harness/SnapshotHelper.d.ts +13 -0
  108. package/dist/e2e/harness/SnapshotHelper.d.ts.map +1 -0
  109. package/dist/e2e/harness/SnapshotHelper.js +36 -0
  110. package/dist/e2e/harness/SnapshotHelper.js.map +1 -0
  111. package/dist/e2e/harness/TestHelpers.d.ts +25 -0
  112. package/dist/e2e/harness/TestHelpers.d.ts.map +1 -0
  113. package/dist/e2e/harness/TestHelpers.js +103 -0
  114. package/dist/e2e/harness/TestHelpers.js.map +1 -0
  115. package/dist/e2e/harness/TestRebalancer.d.ts +85 -0
  116. package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -0
  117. package/dist/e2e/harness/TestRebalancer.js +427 -0
  118. package/dist/e2e/harness/TestRebalancer.js.map +1 -0
  119. package/dist/e2e/harness/TransferHelper.d.ts +34 -0
  120. package/dist/e2e/harness/TransferHelper.d.ts.map +1 -0
  121. package/dist/e2e/harness/TransferHelper.js +93 -0
  122. package/dist/e2e/harness/TransferHelper.js.map +1 -0
  123. package/dist/e2e/inventory-erc20-minAmount.e2e-test.d.ts +2 -0
  124. package/dist/e2e/inventory-erc20-minAmount.e2e-test.d.ts.map +1 -0
  125. package/dist/e2e/inventory-erc20-minAmount.e2e-test.js +411 -0
  126. package/dist/e2e/inventory-erc20-minAmount.e2e-test.js.map +1 -0
  127. package/dist/e2e/inventory-erc20-weighted.e2e-test.d.ts +2 -0
  128. package/dist/e2e/inventory-erc20-weighted.e2e-test.d.ts.map +1 -0
  129. package/dist/e2e/inventory-erc20-weighted.e2e-test.js +408 -0
  130. package/dist/e2e/inventory-erc20-weighted.e2e-test.js.map +1 -0
  131. package/dist/e2e/inventory-minAmount.e2e-test.d.ts +2 -0
  132. package/dist/e2e/inventory-minAmount.e2e-test.d.ts.map +1 -0
  133. package/dist/e2e/inventory-minAmount.e2e-test.js +411 -0
  134. package/dist/e2e/inventory-minAmount.e2e-test.js.map +1 -0
  135. package/dist/e2e/inventory-weighted.e2e-test.d.ts +2 -0
  136. package/dist/e2e/inventory-weighted.e2e-test.d.ts.map +1 -0
  137. package/dist/e2e/inventory-weighted.e2e-test.js +409 -0
  138. package/dist/e2e/inventory-weighted.e2e-test.js.map +1 -0
  139. package/dist/e2e/minAmount.e2e-test.d.ts +2 -0
  140. package/dist/e2e/minAmount.e2e-test.d.ts.map +1 -0
  141. package/dist/e2e/minAmount.e2e-test.js +203 -0
  142. package/dist/e2e/minAmount.e2e-test.js.map +1 -0
  143. package/dist/e2e/mixed-weighted.e2e-test.d.ts +2 -0
  144. package/dist/e2e/mixed-weighted.e2e-test.d.ts.map +1 -0
  145. package/dist/e2e/mixed-weighted.e2e-test.js +189 -0
  146. package/dist/e2e/mixed-weighted.e2e-test.js.map +1 -0
  147. package/dist/e2e/weighted.e2e-test.d.ts +2 -0
  148. package/dist/e2e/weighted.e2e-test.d.ts.map +1 -0
  149. package/dist/e2e/weighted.e2e-test.js +198 -0
  150. package/dist/e2e/weighted.e2e-test.js.map +1 -0
  151. package/dist/factories/RebalancerContextFactory.d.ts +89 -0
  152. package/dist/factories/RebalancerContextFactory.d.ts.map +1 -0
  153. package/dist/factories/RebalancerContextFactory.js +420 -0
  154. package/dist/factories/RebalancerContextFactory.js.map +1 -0
  155. package/dist/factories/RebalancerContextFactory.test.d.ts +2 -0
  156. package/dist/factories/RebalancerContextFactory.test.d.ts.map +1 -0
  157. package/dist/factories/RebalancerContextFactory.test.js +270 -0
  158. package/dist/factories/RebalancerContextFactory.test.js.map +1 -0
  159. package/dist/index.d.ts +37 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +37 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/interfaces/IExternalBridge.d.ts +103 -0
  164. package/dist/interfaces/IExternalBridge.d.ts.map +1 -0
  165. package/dist/interfaces/IExternalBridge.js +2 -0
  166. package/dist/interfaces/IExternalBridge.js.map +1 -0
  167. package/dist/interfaces/IMetrics.d.ts +5 -0
  168. package/dist/interfaces/IMetrics.d.ts.map +1 -0
  169. package/dist/interfaces/IMetrics.js +2 -0
  170. package/dist/interfaces/IMetrics.js.map +1 -0
  171. package/dist/interfaces/IMonitor.d.ts +50 -0
  172. package/dist/interfaces/IMonitor.d.ts.map +1 -0
  173. package/dist/interfaces/IMonitor.js +14 -0
  174. package/dist/interfaces/IMonitor.js.map +1 -0
  175. package/dist/interfaces/IRebalancer.d.ts +31 -0
  176. package/dist/interfaces/IRebalancer.d.ts.map +1 -0
  177. package/dist/interfaces/IRebalancer.js +2 -0
  178. package/dist/interfaces/IRebalancer.js.map +1 -0
  179. package/dist/interfaces/IStrategy.d.ts +60 -0
  180. package/dist/interfaces/IStrategy.d.ts.map +1 -0
  181. package/dist/interfaces/IStrategy.js +13 -0
  182. package/dist/interfaces/IStrategy.js.map +1 -0
  183. package/dist/metrics/Metrics.d.ts +25 -0
  184. package/dist/metrics/Metrics.d.ts.map +1 -0
  185. package/dist/metrics/Metrics.js +164 -0
  186. package/dist/metrics/Metrics.js.map +1 -0
  187. package/dist/metrics/PriceGetter.d.ts +10 -0
  188. package/dist/metrics/PriceGetter.d.ts.map +1 -0
  189. package/dist/metrics/PriceGetter.js +41 -0
  190. package/dist/metrics/PriceGetter.js.map +1 -0
  191. package/dist/metrics/scripts/metrics.d.ts +28 -0
  192. package/dist/metrics/scripts/metrics.d.ts.map +1 -0
  193. package/dist/metrics/scripts/metrics.js +61 -0
  194. package/dist/metrics/scripts/metrics.js.map +1 -0
  195. package/dist/monitor/Monitor.d.ts +40 -0
  196. package/dist/monitor/Monitor.d.ts.map +1 -0
  197. package/dist/monitor/Monitor.js +211 -0
  198. package/dist/monitor/Monitor.js.map +1 -0
  199. package/dist/service.d.ts +3 -0
  200. package/dist/service.d.ts.map +1 -0
  201. package/dist/service.js +205 -0
  202. package/dist/service.js.map +1 -0
  203. package/dist/strategy/BaseStrategy.d.ts +86 -0
  204. package/dist/strategy/BaseStrategy.d.ts.map +1 -0
  205. package/dist/strategy/BaseStrategy.js +342 -0
  206. package/dist/strategy/BaseStrategy.js.map +1 -0
  207. package/dist/strategy/CollateralDeficitStrategy.d.ts +65 -0
  208. package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -0
  209. package/dist/strategy/CollateralDeficitStrategy.js +253 -0
  210. package/dist/strategy/CollateralDeficitStrategy.js.map +1 -0
  211. package/dist/strategy/CollateralDeficitStrategy.test.d.ts +2 -0
  212. package/dist/strategy/CollateralDeficitStrategy.test.d.ts.map +1 -0
  213. package/dist/strategy/CollateralDeficitStrategy.test.js +497 -0
  214. package/dist/strategy/CollateralDeficitStrategy.test.js.map +1 -0
  215. package/dist/strategy/CompositeStrategy.d.ts +18 -0
  216. package/dist/strategy/CompositeStrategy.d.ts.map +1 -0
  217. package/dist/strategy/CompositeStrategy.js +63 -0
  218. package/dist/strategy/CompositeStrategy.js.map +1 -0
  219. package/dist/strategy/CompositeStrategy.test.d.ts +2 -0
  220. package/dist/strategy/CompositeStrategy.test.d.ts.map +1 -0
  221. package/dist/strategy/CompositeStrategy.test.js +278 -0
  222. package/dist/strategy/CompositeStrategy.test.js.map +1 -0
  223. package/dist/strategy/MinAmountStrategy.d.ts +35 -0
  224. package/dist/strategy/MinAmountStrategy.d.ts.map +1 -0
  225. package/dist/strategy/MinAmountStrategy.js +112 -0
  226. package/dist/strategy/MinAmountStrategy.js.map +1 -0
  227. package/dist/strategy/MinAmountStrategy.test.d.ts +2 -0
  228. package/dist/strategy/MinAmountStrategy.test.d.ts.map +1 -0
  229. package/dist/strategy/MinAmountStrategy.test.js +547 -0
  230. package/dist/strategy/MinAmountStrategy.test.js.map +1 -0
  231. package/dist/strategy/StrategyFactory.d.ts +27 -0
  232. package/dist/strategy/StrategyFactory.d.ts.map +1 -0
  233. package/dist/strategy/StrategyFactory.js +79 -0
  234. package/dist/strategy/StrategyFactory.js.map +1 -0
  235. package/dist/strategy/StrategyFactory.test.d.ts +2 -0
  236. package/dist/strategy/StrategyFactory.test.d.ts.map +1 -0
  237. package/dist/strategy/StrategyFactory.test.js +81 -0
  238. package/dist/strategy/StrategyFactory.test.js.map +1 -0
  239. package/dist/strategy/WeightedStrategy.d.ts +32 -0
  240. package/dist/strategy/WeightedStrategy.d.ts.map +1 -0
  241. package/dist/strategy/WeightedStrategy.js +73 -0
  242. package/dist/strategy/WeightedStrategy.js.map +1 -0
  243. package/dist/strategy/WeightedStrategy.test.d.ts +2 -0
  244. package/dist/strategy/WeightedStrategy.test.d.ts.map +1 -0
  245. package/dist/strategy/WeightedStrategy.test.js +403 -0
  246. package/dist/strategy/WeightedStrategy.test.js.map +1 -0
  247. package/dist/strategy/index.d.ts +7 -0
  248. package/dist/strategy/index.d.ts.map +1 -0
  249. package/dist/strategy/index.js +7 -0
  250. package/dist/strategy/index.js.map +1 -0
  251. package/dist/test/helpers.d.ts +99 -0
  252. package/dist/test/helpers.d.ts.map +1 -0
  253. package/dist/test/helpers.js +311 -0
  254. package/dist/test/helpers.js.map +1 -0
  255. package/dist/test/lifiMocks.d.ts +52 -0
  256. package/dist/test/lifiMocks.d.ts.map +1 -0
  257. package/dist/test/lifiMocks.js +160 -0
  258. package/dist/test/lifiMocks.js.map +1 -0
  259. package/dist/tracking/ActionTracker.d.ts +90 -0
  260. package/dist/tracking/ActionTracker.d.ts.map +1 -0
  261. package/dist/tracking/ActionTracker.js +678 -0
  262. package/dist/tracking/ActionTracker.js.map +1 -0
  263. package/dist/tracking/ActionTracker.test.d.ts +2 -0
  264. package/dist/tracking/ActionTracker.test.d.ts.map +1 -0
  265. package/dist/tracking/ActionTracker.test.js +1351 -0
  266. package/dist/tracking/ActionTracker.test.js.map +1 -0
  267. package/dist/tracking/IActionTracker.d.ts +157 -0
  268. package/dist/tracking/IActionTracker.d.ts.map +1 -0
  269. package/dist/tracking/IActionTracker.js +2 -0
  270. package/dist/tracking/IActionTracker.js.map +1 -0
  271. package/dist/tracking/InflightContextAdapter.d.ts +18 -0
  272. package/dist/tracking/InflightContextAdapter.d.ts.map +1 -0
  273. package/dist/tracking/InflightContextAdapter.js +52 -0
  274. package/dist/tracking/InflightContextAdapter.js.map +1 -0
  275. package/dist/tracking/InflightContextAdapter.test.d.ts +2 -0
  276. package/dist/tracking/InflightContextAdapter.test.d.ts.map +1 -0
  277. package/dist/tracking/InflightContextAdapter.test.js +175 -0
  278. package/dist/tracking/InflightContextAdapter.test.js.map +1 -0
  279. package/dist/tracking/store/IStore.d.ts +41 -0
  280. package/dist/tracking/store/IStore.d.ts.map +1 -0
  281. package/dist/tracking/store/IStore.js +2 -0
  282. package/dist/tracking/store/IStore.js.map +1 -0
  283. package/dist/tracking/store/InMemoryStore.d.ts +21 -0
  284. package/dist/tracking/store/InMemoryStore.d.ts.map +1 -0
  285. package/dist/tracking/store/InMemoryStore.js +40 -0
  286. package/dist/tracking/store/InMemoryStore.js.map +1 -0
  287. package/dist/tracking/store/InMemoryStore.test.d.ts +2 -0
  288. package/dist/tracking/store/InMemoryStore.test.d.ts.map +1 -0
  289. package/dist/tracking/store/InMemoryStore.test.js +290 -0
  290. package/dist/tracking/store/InMemoryStore.test.js.map +1 -0
  291. package/dist/tracking/store/index.d.ts +3 -0
  292. package/dist/tracking/store/index.d.ts.map +1 -0
  293. package/dist/tracking/store/index.js +2 -0
  294. package/dist/tracking/store/index.js.map +1 -0
  295. package/dist/tracking/types.d.ts +77 -0
  296. package/dist/tracking/types.d.ts.map +1 -0
  297. package/dist/tracking/types.js +2 -0
  298. package/dist/tracking/types.js.map +1 -0
  299. package/dist/utils/ExplorerClient.d.ts +68 -0
  300. package/dist/utils/ExplorerClient.d.ts.map +1 -0
  301. package/dist/utils/ExplorerClient.js +324 -0
  302. package/dist/utils/ExplorerClient.js.map +1 -0
  303. package/dist/utils/ExplorerClient.test.d.ts +2 -0
  304. package/dist/utils/ExplorerClient.test.d.ts.map +1 -0
  305. package/dist/utils/ExplorerClient.test.js +261 -0
  306. package/dist/utils/ExplorerClient.test.js.map +1 -0
  307. package/dist/utils/balanceUtils.d.ts +12 -0
  308. package/dist/utils/balanceUtils.d.ts.map +1 -0
  309. package/dist/utils/balanceUtils.js +40 -0
  310. package/dist/utils/balanceUtils.js.map +1 -0
  311. package/dist/utils/balanceUtils.test.d.ts +2 -0
  312. package/dist/utils/balanceUtils.test.d.ts.map +1 -0
  313. package/dist/utils/balanceUtils.test.js +55 -0
  314. package/dist/utils/balanceUtils.test.js.map +1 -0
  315. package/dist/utils/blockTag.d.ts +14 -0
  316. package/dist/utils/blockTag.d.ts.map +1 -0
  317. package/dist/utils/blockTag.js +46 -0
  318. package/dist/utils/blockTag.js.map +1 -0
  319. package/dist/utils/bridgeUtils.d.ts +40 -0
  320. package/dist/utils/bridgeUtils.d.ts.map +1 -0
  321. package/dist/utils/bridgeUtils.js +54 -0
  322. package/dist/utils/bridgeUtils.js.map +1 -0
  323. package/dist/utils/bridgeUtils.test.d.ts +2 -0
  324. package/dist/utils/bridgeUtils.test.d.ts.map +1 -0
  325. package/dist/utils/bridgeUtils.test.js +163 -0
  326. package/dist/utils/bridgeUtils.test.js.map +1 -0
  327. package/dist/utils/errors.d.ts +4 -0
  328. package/dist/utils/errors.d.ts.map +1 -0
  329. package/dist/utils/errors.js +6 -0
  330. package/dist/utils/errors.js.map +1 -0
  331. package/dist/utils/gasEstimation.d.ts +65 -0
  332. package/dist/utils/gasEstimation.d.ts.map +1 -0
  333. package/dist/utils/gasEstimation.js +206 -0
  334. package/dist/utils/gasEstimation.js.map +1 -0
  335. package/dist/utils/solanaKeyParser.d.ts +10 -0
  336. package/dist/utils/solanaKeyParser.d.ts.map +1 -0
  337. package/dist/utils/solanaKeyParser.js +87 -0
  338. package/dist/utils/solanaKeyParser.js.map +1 -0
  339. package/dist/utils/solanaKeyParser.test.d.ts +2 -0
  340. package/dist/utils/solanaKeyParser.test.d.ts.map +1 -0
  341. package/dist/utils/solanaKeyParser.test.js +71 -0
  342. package/dist/utils/solanaKeyParser.test.js.map +1 -0
  343. package/dist/utils/tokenUtils.d.ts +38 -0
  344. package/dist/utils/tokenUtils.d.ts.map +1 -0
  345. package/dist/utils/tokenUtils.js +65 -0
  346. package/dist/utils/tokenUtils.js.map +1 -0
  347. package/dist/utils/transactionUtils.d.ts +22 -0
  348. package/dist/utils/transactionUtils.d.ts.map +1 -0
  349. package/dist/utils/transactionUtils.js +26 -0
  350. package/dist/utils/transactionUtils.js.map +1 -0
  351. package/package.json +87 -3
  352. package/src/bridges/LiFiBridge.test.ts +615 -0
  353. package/src/bridges/LiFiBridge.ts +731 -0
  354. package/src/config/RebalancerConfig.test.ts +921 -0
  355. package/src/config/RebalancerConfig.ts +63 -0
  356. package/src/config/types.ts +613 -0
  357. package/src/core/InventoryRebalancer.test.ts +1858 -0
  358. package/src/core/InventoryRebalancer.ts +1455 -0
  359. package/src/core/Rebalancer.test.ts +686 -0
  360. package/src/core/Rebalancer.ts +686 -0
  361. package/src/core/RebalancerOrchestrator.test.ts +871 -0
  362. package/src/core/RebalancerOrchestrator.ts +273 -0
  363. package/src/core/RebalancerService.test.ts +1094 -0
  364. package/src/core/RebalancerService.ts +412 -0
  365. package/src/e2e/E2E_TEST_CONVENTIONS.md +222 -0
  366. package/src/e2e/collateral-deficit.e2e-test.ts +403 -0
  367. package/src/e2e/composite.e2e-test.ts +1008 -0
  368. package/src/e2e/fixtures/routes.ts +532 -0
  369. package/src/e2e/harness/BaseLocalDeploymentManager.ts +246 -0
  370. package/src/e2e/harness/BridgeSetup.ts +95 -0
  371. package/src/e2e/harness/Erc20InventoryLocalDeploymentManager.ts +183 -0
  372. package/src/e2e/harness/Erc20LocalDeploymentManager.ts +190 -0
  373. package/src/e2e/harness/ForkIndexer.test.ts +448 -0
  374. package/src/e2e/harness/ForkIndexer.ts +183 -0
  375. package/src/e2e/harness/MixedLocalDeploymentManager.ts +196 -0
  376. package/src/e2e/harness/MockExplorerClient.ts +94 -0
  377. package/src/e2e/harness/MockExternalBridge.ts +411 -0
  378. package/src/e2e/harness/NativeLocalDeploymentManager.ts +138 -0
  379. package/src/e2e/harness/SnapshotHelper.ts +56 -0
  380. package/src/e2e/harness/TestHelpers.ts +169 -0
  381. package/src/e2e/harness/TestRebalancer.ts +758 -0
  382. package/src/e2e/harness/TransferHelper.ts +188 -0
  383. package/src/e2e/inventory-erc20-minAmount.e2e-test.ts +735 -0
  384. package/src/e2e/inventory-erc20-weighted.e2e-test.ts +733 -0
  385. package/src/e2e/inventory-minAmount.e2e-test.ts +734 -0
  386. package/src/e2e/inventory-weighted.e2e-test.ts +734 -0
  387. package/src/e2e/minAmount.e2e-test.ts +313 -0
  388. package/src/e2e/mixed-weighted.e2e-test.ts +267 -0
  389. package/src/e2e/weighted.e2e-test.ts +304 -0
  390. package/src/factories/RebalancerContextFactory.test.ts +394 -0
  391. package/src/factories/RebalancerContextFactory.ts +771 -0
  392. package/src/index.ts +125 -0
  393. package/src/interfaces/IExternalBridge.ts +117 -0
  394. package/src/interfaces/IMetrics.ts +5 -0
  395. package/src/interfaces/IMonitor.ts +71 -0
  396. package/src/interfaces/IRebalancer.ts +57 -0
  397. package/src/interfaces/IStrategy.ts +81 -0
  398. package/src/metrics/Metrics.ts +335 -0
  399. package/src/metrics/PriceGetter.ts +74 -0
  400. package/src/metrics/scripts/metrics.ts +139 -0
  401. package/src/monitor/Monitor.ts +324 -0
  402. package/src/service.ts +285 -0
  403. package/src/strategy/BaseStrategy.ts +553 -0
  404. package/src/strategy/CollateralDeficitStrategy.test.ts +728 -0
  405. package/src/strategy/CollateralDeficitStrategy.ts +421 -0
  406. package/src/strategy/CompositeStrategy.test.ts +418 -0
  407. package/src/strategy/CompositeStrategy.ts +102 -0
  408. package/src/strategy/MinAmountStrategy.test.ts +732 -0
  409. package/src/strategy/MinAmountStrategy.ts +200 -0
  410. package/src/strategy/StrategyFactory.test.ts +108 -0
  411. package/src/strategy/StrategyFactory.ts +157 -0
  412. package/src/strategy/WeightedStrategy.test.ts +529 -0
  413. package/src/strategy/WeightedStrategy.ts +126 -0
  414. package/src/strategy/index.ts +6 -0
  415. package/src/test/helpers.ts +477 -0
  416. package/src/test/lifiMocks.ts +211 -0
  417. package/src/tracking/ActionTracker.test.ts +1625 -0
  418. package/src/tracking/ActionTracker.ts +1019 -0
  419. package/src/tracking/IActionTracker.ts +213 -0
  420. package/src/tracking/InflightContextAdapter.test.ts +206 -0
  421. package/src/tracking/InflightContextAdapter.ts +75 -0
  422. package/src/tracking/store/IStore.ts +48 -0
  423. package/src/tracking/store/InMemoryStore.test.ts +338 -0
  424. package/src/tracking/store/InMemoryStore.ts +59 -0
  425. package/src/tracking/store/index.ts +2 -0
  426. package/src/tracking/types.ts +118 -0
  427. package/src/utils/ExplorerClient.test.ts +386 -0
  428. package/src/utils/ExplorerClient.ts +439 -0
  429. package/src/utils/balanceUtils.test.ts +79 -0
  430. package/src/utils/balanceUtils.ts +65 -0
  431. package/src/utils/blockTag.ts +68 -0
  432. package/src/utils/bridgeUtils.test.ts +193 -0
  433. package/src/utils/bridgeUtils.ts +101 -0
  434. package/src/utils/errors.ts +5 -0
  435. package/src/utils/gasEstimation.ts +306 -0
  436. package/src/utils/solanaKeyParser.test.ts +103 -0
  437. package/src/utils/solanaKeyParser.ts +117 -0
  438. package/src/utils/tokenUtils.ts +89 -0
  439. package/src/utils/transactionUtils.ts +41 -0
@@ -0,0 +1,734 @@
1
+ import { expect } from 'chai';
2
+ import { ethers, providers } from 'ethers';
3
+
4
+ import {
5
+ HyperlaneCore,
6
+ MultiProvider,
7
+ snapshot,
8
+ } from '@humanode-hyperlane/sdk';
9
+
10
+ import { ExternalBridgeType } from '../config/types.js';
11
+
12
+ import {
13
+ ANVIL_USER_PRIVATE_KEY,
14
+ DOMAIN_IDS,
15
+ TEST_CHAINS,
16
+ type NativeDeployedAddresses,
17
+ buildInventoryWeightedStrategyConfig,
18
+ WEIGHTED_EXPECTED_DEFICIT_1ETH,
19
+ WEIGHTED_EXPECTED_DEFICIT_1_2ETH,
20
+ WEIGHTED_EXPECTED_DEFICIT_2ETH,
21
+ } from './fixtures/routes.js';
22
+ import { MockExternalBridge } from './harness/MockExternalBridge.js';
23
+ import { NativeLocalDeploymentManager } from './harness/NativeLocalDeploymentManager.js';
24
+ import { resetSnapshotsAndRefreshProviders } from './harness/SnapshotHelper.js';
25
+ import {
26
+ getFirstMonitorEvent,
27
+ relayInProgressInventoryDeposits,
28
+ getRouterBalances,
29
+ classifyChains,
30
+ } from './harness/TestHelpers.js';
31
+ import {
32
+ type TestRebalancerContext,
33
+ TestRebalancerBuilder,
34
+ } from './harness/TestRebalancer.js';
35
+
36
+ describe('Inventory WeightedStrategy E2E', function () {
37
+ this.timeout(300_000);
38
+
39
+ let deploymentManager: NativeLocalDeploymentManager;
40
+ let multiProvider: MultiProvider;
41
+ let localProviders: Map<string, providers.JsonRpcProvider>;
42
+ let snapshotIds: Map<string, string>;
43
+ let hyperlaneCore: HyperlaneCore;
44
+ let nativeDeployedAddresses: NativeDeployedAddresses;
45
+ let weightedStrategyConfig: ReturnType<
46
+ typeof buildInventoryWeightedStrategyConfig
47
+ >;
48
+ let mockBridge: MockExternalBridge;
49
+
50
+ const inventorySignerAddress = new ethers.Wallet(ANVIL_USER_PRIVATE_KEY)
51
+ .address;
52
+
53
+ async function executeCycle(context: TestRebalancerContext): Promise<void> {
54
+ const monitor = context.createMonitor(0);
55
+ const event = await getFirstMonitorEvent(monitor);
56
+ await context.orchestrator.executeCycle(event);
57
+ }
58
+
59
+ before(async function () {
60
+ deploymentManager = new NativeLocalDeploymentManager(
61
+ inventorySignerAddress,
62
+ );
63
+ const ctx = await deploymentManager.start();
64
+ multiProvider = ctx.multiProvider;
65
+ localProviders = ctx.providers;
66
+ nativeDeployedAddresses = ctx.deployedAddresses;
67
+
68
+ const coreAddresses: Record<string, Record<string, string>> = {};
69
+ for (const chain of TEST_CHAINS) {
70
+ coreAddresses[chain] = {
71
+ mailbox: nativeDeployedAddresses.chains[chain].mailbox,
72
+ interchainSecurityModule: nativeDeployedAddresses.chains[chain].ism,
73
+ };
74
+ }
75
+ hyperlaneCore = HyperlaneCore.fromAddressesMap(
76
+ coreAddresses,
77
+ multiProvider,
78
+ );
79
+
80
+ weightedStrategyConfig = buildInventoryWeightedStrategyConfig(
81
+ nativeDeployedAddresses,
82
+ );
83
+ mockBridge = new MockExternalBridge(
84
+ nativeDeployedAddresses,
85
+ multiProvider,
86
+ hyperlaneCore,
87
+ );
88
+
89
+ snapshotIds = new Map();
90
+ for (const [chain, provider] of localProviders) {
91
+ snapshotIds.set(chain, await snapshot(provider));
92
+ }
93
+ });
94
+
95
+ afterEach(async function () {
96
+ mockBridge.reset();
97
+ await resetSnapshotsAndRefreshProviders({
98
+ localProviders,
99
+ multiProvider,
100
+ snapshotIds,
101
+ });
102
+ });
103
+
104
+ after(async function () {
105
+ if (deploymentManager) {
106
+ await deploymentManager.stop();
107
+ }
108
+ });
109
+
110
+ it('creates direct inventory_deposit when destination has enough inventory', async function () {
111
+ const context = await new TestRebalancerBuilder(
112
+ deploymentManager,
113
+ multiProvider,
114
+ )
115
+ .withStrategy(weightedStrategyConfig)
116
+ .withExecutionMode('execute')
117
+ .withInventoryConfig({
118
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
119
+ nativeDeployedAddresses,
120
+ })
121
+ .withMockExternalBridge(mockBridge)
122
+ .withBalances('INVENTORY_WEIGHTED_IMBALANCED')
123
+ .build();
124
+
125
+ const initialBalances = await getRouterBalances(
126
+ localProviders,
127
+ nativeDeployedAddresses,
128
+ );
129
+
130
+ await executeCycle(context);
131
+
132
+ const activeIntents = await context.tracker.getActiveRebalanceIntents();
133
+ expect(activeIntents.length).to.equal(1);
134
+ expect(activeIntents[0].destination).to.equal(DOMAIN_IDS.anvil3);
135
+ expect(activeIntents[0].amount).to.equal(
136
+ WEIGHTED_EXPECTED_DEFICIT_1ETH.toBigInt(),
137
+ );
138
+ const inProgressActions = await context.tracker.getInProgressActions();
139
+ expect(inProgressActions.length).to.equal(1);
140
+ const depositAction = inProgressActions.find(
141
+ (a) => a.type === 'inventory_deposit',
142
+ );
143
+ expect(depositAction).to.exist;
144
+
145
+ await relayInProgressInventoryDeposits(
146
+ context,
147
+ localProviders,
148
+ multiProvider,
149
+ hyperlaneCore,
150
+ );
151
+
152
+ const completedAction = await context.tracker.getRebalanceAction(
153
+ depositAction!.id,
154
+ );
155
+ expect(completedAction!.status).to.equal('complete');
156
+
157
+ const completedIntent = await context.tracker.getRebalanceIntent(
158
+ activeIntents[0].id,
159
+ );
160
+ expect(completedIntent?.status).to.equal('complete');
161
+
162
+ const finalBalances = await getRouterBalances(
163
+ localProviders,
164
+ nativeDeployedAddresses,
165
+ );
166
+ const { surplusChain, neutralChain } = classifyChains(
167
+ 'anvil3',
168
+ depositAction!,
169
+ );
170
+
171
+ expect(
172
+ finalBalances.anvil3.gt(initialBalances.anvil3),
173
+ 'Deficit router (anvil3) balance should increase',
174
+ ).to.be.true;
175
+ expect(
176
+ finalBalances[surplusChain].lt(initialBalances[surplusChain]),
177
+ `Surplus router (${surplusChain}) balance should decrease`,
178
+ ).to.be.true;
179
+ if (neutralChain) {
180
+ expect(
181
+ finalBalances[neutralChain].eq(initialBalances[neutralChain]),
182
+ 'Uninvolved router balance should remain unchanged',
183
+ ).to.be.true;
184
+ }
185
+ });
186
+
187
+ it('handles partial deposit, then bridge, then final deposit', async function () {
188
+ const context = await new TestRebalancerBuilder(
189
+ deploymentManager,
190
+ multiProvider,
191
+ )
192
+ .withStrategy(weightedStrategyConfig)
193
+ .withExecutionMode('execute')
194
+ .withInventoryConfig({
195
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
196
+ nativeDeployedAddresses,
197
+ })
198
+ .withMockExternalBridge(mockBridge)
199
+ .withInventorySignerBalances('SIGNER_PARTIAL_ANVIL3')
200
+ .withBalances('INVENTORY_WEIGHTED_IMBALANCED')
201
+ .build();
202
+
203
+ await executeCycle(context);
204
+ await relayInProgressInventoryDeposits(
205
+ context,
206
+ localProviders,
207
+ multiProvider,
208
+ hyperlaneCore,
209
+ );
210
+
211
+ const partialIntents =
212
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
213
+ expect(partialIntents.length).to.equal(1);
214
+ expect(partialIntents[0].intent.amount).to.equal(
215
+ WEIGHTED_EXPECTED_DEFICIT_1ETH.toBigInt(),
216
+ );
217
+ expect(partialIntents[0].intent.destination).to.equal(DOMAIN_IDS.anvil3);
218
+ expect(partialIntents[0].completedAmount > 0n).to.be.true;
219
+ expect(
220
+ partialIntents[0].completedAmount + partialIntents[0].remaining,
221
+ ).to.equal(WEIGHTED_EXPECTED_DEFICIT_1ETH.toBigInt());
222
+
223
+ const firstCycleActions = await context.tracker.getActionsForIntent(
224
+ partialIntents[0].intent.id,
225
+ );
226
+ expect(firstCycleActions.length).to.equal(1);
227
+ expect(firstCycleActions[0].type).to.equal('inventory_deposit');
228
+ expect(firstCycleActions[0].origin).to.equal(DOMAIN_IDS.anvil3);
229
+ expect(firstCycleActions[0].amount).to.equal(
230
+ partialIntents[0].completedAmount,
231
+ );
232
+
233
+ const intentId = partialIntents[0].intent.id;
234
+
235
+ await executeCycle(context);
236
+
237
+ const inProgressActions = await context.tracker.getInProgressActions();
238
+ expect(inProgressActions.length).to.equal(1);
239
+ const movementAction = inProgressActions.find(
240
+ (action) => action.type === 'inventory_movement',
241
+ );
242
+ expect(movementAction).to.exist;
243
+ expect(movementAction!.origin).to.equal(DOMAIN_IDS.anvil1);
244
+ expect(movementAction!.destination).to.equal(DOMAIN_IDS.anvil3);
245
+ expect(movementAction!.status).to.equal('in_progress');
246
+
247
+ await context.tracker.syncInventoryMovementActions({
248
+ [ExternalBridgeType.LiFi]: mockBridge,
249
+ });
250
+
251
+ const movementState = await context.tracker.getRebalanceAction(
252
+ movementAction!.id,
253
+ );
254
+ expect(movementState?.status).to.equal('complete');
255
+
256
+ await executeCycle(context);
257
+ await context.tracker.syncInventoryMovementActions({
258
+ [ExternalBridgeType.LiFi]: mockBridge,
259
+ });
260
+ await relayInProgressInventoryDeposits(
261
+ context,
262
+ localProviders,
263
+ multiProvider,
264
+ hyperlaneCore,
265
+ );
266
+
267
+ const partialAfterFinalCycle =
268
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
269
+ expect(partialAfterFinalCycle.length).to.equal(0);
270
+
271
+ const completedIntent = await context.tracker.getRebalanceIntent(intentId);
272
+ expect(completedIntent?.status).to.equal('complete');
273
+
274
+ const actions = await context.tracker.getActionsForIntent(intentId);
275
+ const allDeposits = actions.filter((a) => a.type === 'inventory_deposit');
276
+ const movements = actions.filter((a) => a.type === 'inventory_movement');
277
+ expect(actions.length).to.equal(3);
278
+ expect(movements.length).to.equal(1);
279
+ expect(allDeposits.length).to.equal(2);
280
+ const totalDeposited = allDeposits.reduce((sum, a) => sum + a.amount, 0n);
281
+ expect(totalDeposited).to.equal(completedIntent!.amount);
282
+ });
283
+
284
+ it('completes intent after multiple partial inventory fill cycles', async function () {
285
+ const context = await new TestRebalancerBuilder(
286
+ deploymentManager,
287
+ multiProvider,
288
+ )
289
+ .withStrategy(weightedStrategyConfig)
290
+ .withExecutionMode('execute')
291
+ .withInventoryConfig({
292
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
293
+ nativeDeployedAddresses,
294
+ })
295
+ .withMockExternalBridge(mockBridge)
296
+ .withInventorySignerBalances('SIGNER_WEIGHTED_LOW_ALL')
297
+ .withBalances('INVENTORY_WEIGHTED_ALL_ANVIL1')
298
+ .build();
299
+
300
+ await executeCycle(context);
301
+ await context.tracker.syncInventoryMovementActions({
302
+ [ExternalBridgeType.LiFi]: mockBridge,
303
+ });
304
+ await relayInProgressInventoryDeposits(
305
+ context,
306
+ localProviders,
307
+ multiProvider,
308
+ hyperlaneCore,
309
+ );
310
+
311
+ let activeIntents = await context.tracker.getActiveRebalanceIntents();
312
+ expect(activeIntents.length).to.equal(1);
313
+ expect(activeIntents[0].destination).to.equal(DOMAIN_IDS.anvil2);
314
+ expect(activeIntents[0].amount).to.equal(
315
+ WEIGHTED_EXPECTED_DEFICIT_2ETH.toBigInt(),
316
+ );
317
+ const trackedIntentId = activeIntents[0].id;
318
+
319
+ let partialIntents =
320
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
321
+ expect(partialIntents.length).to.equal(1);
322
+ expect(partialIntents[0].completedAmount > 0n).to.be.true;
323
+ expect(
324
+ partialIntents[0].completedAmount + partialIntents[0].remaining,
325
+ ).to.equal(WEIGHTED_EXPECTED_DEFICIT_2ETH.toBigInt());
326
+
327
+ let actions = await context.tracker.getActionsForIntent(trackedIntentId);
328
+ let movementActions = actions.filter(
329
+ (a) => a.type === 'inventory_movement',
330
+ );
331
+ let depositActions = actions.filter((a) => a.type === 'inventory_deposit');
332
+ expect(actions.length).to.equal(1);
333
+ expect(movementActions.length).to.equal(0);
334
+ expect(depositActions.length).to.equal(1);
335
+ const c0Amount = partialIntents[0].completedAmount;
336
+
337
+ await executeCycle(context);
338
+ await context.tracker.syncInventoryMovementActions({
339
+ [ExternalBridgeType.LiFi]: mockBridge,
340
+ });
341
+ await relayInProgressInventoryDeposits(
342
+ context,
343
+ localProviders,
344
+ multiProvider,
345
+ hyperlaneCore,
346
+ );
347
+
348
+ activeIntents = await context.tracker.getActiveRebalanceIntents();
349
+ expect(activeIntents.length).to.equal(1);
350
+ partialIntents =
351
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
352
+ expect(partialIntents.length).to.equal(1);
353
+ expect(
354
+ partialIntents[0].completedAmount + partialIntents[0].remaining,
355
+ ).to.equal(WEIGHTED_EXPECTED_DEFICIT_2ETH.toBigInt());
356
+
357
+ actions = await context.tracker.getActionsForIntent(trackedIntentId);
358
+ movementActions = actions.filter((a) => a.type === 'inventory_movement');
359
+ depositActions = actions.filter((a) => a.type === 'inventory_deposit');
360
+ expect(actions.length).to.equal(2);
361
+ expect(movementActions.length).to.equal(1);
362
+ expect(depositActions.length).to.equal(1);
363
+ expect(movementActions[0].origin).to.equal(DOMAIN_IDS.anvil1);
364
+ expect(movementActions[0].destination).to.equal(DOMAIN_IDS.anvil2);
365
+ expect(movementActions[0].status).to.equal('complete');
366
+ expect(partialIntents[0].completedAmount).to.equal(c0Amount);
367
+
368
+ await executeCycle(context);
369
+ await context.tracker.syncInventoryMovementActions({
370
+ [ExternalBridgeType.LiFi]: mockBridge,
371
+ });
372
+ await relayInProgressInventoryDeposits(
373
+ context,
374
+ localProviders,
375
+ multiProvider,
376
+ hyperlaneCore,
377
+ );
378
+
379
+ activeIntents = await context.tracker.getActiveRebalanceIntents();
380
+ expect(activeIntents.length).to.equal(0);
381
+ partialIntents =
382
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
383
+ expect(partialIntents.length).to.equal(0);
384
+
385
+ actions = await context.tracker.getActionsForIntent(trackedIntentId);
386
+ movementActions = actions.filter((a) => a.type === 'inventory_movement');
387
+ depositActions = actions.filter((a) => a.type === 'inventory_deposit');
388
+ expect(actions.length).to.equal(3);
389
+ expect(movementActions.length).to.equal(1);
390
+ expect(depositActions.length).to.equal(2);
391
+
392
+ const completedIntent =
393
+ await context.tracker.getRebalanceIntent(trackedIntentId);
394
+ expect(completedIntent?.status).to.equal('complete');
395
+ });
396
+
397
+ it('retries after bridge execution failure', async function () {
398
+ const context = await new TestRebalancerBuilder(
399
+ deploymentManager,
400
+ multiProvider,
401
+ )
402
+ .withStrategy(weightedStrategyConfig)
403
+ .withExecutionMode('execute')
404
+ .withInventoryConfig({
405
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
406
+ nativeDeployedAddresses,
407
+ })
408
+ .withMockExternalBridge(mockBridge)
409
+ .withInventorySignerBalances('SIGNER_ZERO_ANVIL3')
410
+ .withBalances('INVENTORY_WEIGHTED_IMBALANCED')
411
+ .build();
412
+
413
+ const initialBalances = await getRouterBalances(
414
+ localProviders,
415
+ nativeDeployedAddresses,
416
+ );
417
+
418
+ // Cycle 1: Bridge fails — intent created but stays not_started, no actions
419
+ mockBridge.failNextExecute();
420
+ await executeCycle(context);
421
+
422
+ const activeIntents = await context.tracker.getActiveRebalanceIntents();
423
+ expect(activeIntents.length).to.equal(0);
424
+
425
+ const partialIntents =
426
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
427
+ expect(partialIntents.length).to.equal(1);
428
+ expect(partialIntents[0].intent.status).to.equal('not_started');
429
+ expect(partialIntents[0].completedAmount).to.equal(0n);
430
+ expect(partialIntents[0].remaining).to.equal(
431
+ WEIGHTED_EXPECTED_DEFICIT_1ETH.toBigInt(),
432
+ );
433
+
434
+ const intentId = partialIntents[0].intent.id;
435
+ const actionsAfterFailure =
436
+ await context.tracker.getActionsForIntent(intentId);
437
+ expect(actionsAfterFailure.length).to.equal(0);
438
+
439
+ // Cycle 2: Bridge succeeds — creates movement, intent becomes in_progress
440
+ await executeCycle(context);
441
+ await context.tracker.syncInventoryMovementActions({
442
+ [ExternalBridgeType.LiFi]: mockBridge,
443
+ });
444
+ await relayInProgressInventoryDeposits(
445
+ context,
446
+ localProviders,
447
+ multiProvider,
448
+ hyperlaneCore,
449
+ );
450
+
451
+ const cycle2Active = await context.tracker.getActiveRebalanceIntents();
452
+ expect(cycle2Active.length).to.equal(1);
453
+ const cycle2Partial =
454
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
455
+ expect(cycle2Partial.length).to.equal(1);
456
+
457
+ const cycle2Actions = await context.tracker.getActionsForIntent(intentId);
458
+ expect(cycle2Actions.length).to.equal(1);
459
+ const movementAction = cycle2Actions.find(
460
+ (a) => a.type === 'inventory_movement',
461
+ );
462
+ expect(movementAction).to.exist;
463
+ expect(movementAction!.status).to.equal('complete');
464
+
465
+ const cycle2Intent = await context.tracker.getRebalanceIntent(intentId);
466
+ expect(cycle2Intent!.status).to.equal('in_progress');
467
+
468
+ // Cycle 3: Deposit completes the intent
469
+ await executeCycle(context);
470
+ await context.tracker.syncInventoryMovementActions({
471
+ [ExternalBridgeType.LiFi]: mockBridge,
472
+ });
473
+ await relayInProgressInventoryDeposits(
474
+ context,
475
+ localProviders,
476
+ multiProvider,
477
+ hyperlaneCore,
478
+ );
479
+
480
+ const completedIntent = await context.tracker.getRebalanceIntent(intentId);
481
+ expect(completedIntent!.status).to.equal('complete');
482
+
483
+ const finalActions = await context.tracker.getActionsForIntent(intentId);
484
+ expect(finalActions.length).to.equal(2);
485
+ const finalMovement = finalActions.find(
486
+ (a) => a.type === 'inventory_movement',
487
+ );
488
+ expect(finalMovement).to.exist;
489
+ const depositAction = finalActions.find(
490
+ (a) => a.type === 'inventory_deposit',
491
+ );
492
+ expect(depositAction).to.exist;
493
+
494
+ const finalBalances = await getRouterBalances(
495
+ localProviders,
496
+ nativeDeployedAddresses,
497
+ );
498
+ const { surplusChain, neutralChain } = classifyChains(
499
+ 'anvil3',
500
+ depositAction!,
501
+ );
502
+
503
+ expect(
504
+ finalBalances.anvil3.gt(initialBalances.anvil3),
505
+ 'Deficit router (anvil3) balance should increase',
506
+ ).to.be.true;
507
+ expect(
508
+ finalBalances[surplusChain].lt(initialBalances[surplusChain]),
509
+ `Surplus router (${surplusChain}) balance should decrease`,
510
+ ).to.be.true;
511
+ if (neutralChain) {
512
+ expect(
513
+ finalBalances[neutralChain].eq(initialBalances[neutralChain]),
514
+ 'Uninvolved router balance should remain unchanged',
515
+ ).to.be.true;
516
+ }
517
+ });
518
+
519
+ it('enforces single active inventory intent when multiple routes are proposed', async function () {
520
+ const context = await new TestRebalancerBuilder(
521
+ deploymentManager,
522
+ multiProvider,
523
+ )
524
+ .withStrategy(weightedStrategyConfig)
525
+ .withExecutionMode('execute')
526
+ .withInventoryConfig({
527
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
528
+ nativeDeployedAddresses,
529
+ })
530
+ .withMockExternalBridge(mockBridge)
531
+ .withBalances('INVENTORY_WEIGHTED_ALL_ANVIL1')
532
+ .build();
533
+
534
+ const initialBalances = await getRouterBalances(
535
+ localProviders,
536
+ nativeDeployedAddresses,
537
+ );
538
+
539
+ await executeCycle(context);
540
+
541
+ const firstCycleIntents = await context.tracker.getActiveRebalanceIntents();
542
+ expect(firstCycleIntents.length).to.equal(1);
543
+ expect(firstCycleIntents[0].destination).to.equal(DOMAIN_IDS.anvil2);
544
+ expect(firstCycleIntents[0].amount).to.equal(
545
+ WEIGHTED_EXPECTED_DEFICIT_2ETH.toBigInt(),
546
+ );
547
+
548
+ const firstIntentId = firstCycleIntents[0].id;
549
+ let partialIntents =
550
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
551
+ expect(partialIntents.length).to.equal(1);
552
+ expect(partialIntents[0].hasInflightDeposit).to.equal(true);
553
+
554
+ await context.tracker.syncInventoryMovementActions({
555
+ [ExternalBridgeType.LiFi]: mockBridge,
556
+ });
557
+ await relayInProgressInventoryDeposits(
558
+ context,
559
+ localProviders,
560
+ multiProvider,
561
+ hyperlaneCore,
562
+ );
563
+
564
+ partialIntents =
565
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
566
+ expect(partialIntents.length).to.equal(0);
567
+ const actions = await context.tracker.getActionsForIntent(firstIntentId);
568
+ expect(actions.length).to.equal(1);
569
+ const movementCount = actions.filter(
570
+ (a) => a.type === 'inventory_movement',
571
+ ).length;
572
+ const depositCount = actions.filter(
573
+ (a) => a.type === 'inventory_deposit',
574
+ ).length;
575
+ expect(movementCount).to.equal(0);
576
+ expect(depositCount).to.equal(1);
577
+
578
+ const completedFirstIntent =
579
+ await context.tracker.getRebalanceIntent(firstIntentId);
580
+ expect(completedFirstIntent?.status).to.equal('complete');
581
+
582
+ const finalBalances = await getRouterBalances(
583
+ localProviders,
584
+ nativeDeployedAddresses,
585
+ );
586
+ const depositAction = await context.tracker.getRebalanceAction(
587
+ actions.find((a) => a.type === 'inventory_deposit')!.id,
588
+ );
589
+ const { surplusChain, neutralChain } = classifyChains(
590
+ 'anvil2',
591
+ depositAction!,
592
+ );
593
+
594
+ expect(
595
+ finalBalances.anvil2.gt(initialBalances.anvil2),
596
+ 'Deficit router (anvil2) balance should increase',
597
+ ).to.be.true;
598
+ expect(
599
+ finalBalances[surplusChain].lt(initialBalances[surplusChain]),
600
+ `Surplus router (${surplusChain}) balance should decrease`,
601
+ ).to.be.true;
602
+ if (neutralChain) {
603
+ expect(
604
+ finalBalances[neutralChain].eq(initialBalances[neutralChain]),
605
+ 'Uninvolved router balance should remain unchanged',
606
+ ).to.be.true;
607
+ }
608
+
609
+ await executeCycle(context);
610
+ const secondCycleIntents =
611
+ await context.tracker.getActiveRebalanceIntents();
612
+ expect(secondCycleIntents.length).to.equal(1);
613
+ expect(secondCycleIntents[0].destination).to.equal(DOMAIN_IDS.anvil3);
614
+ expect(secondCycleIntents[0].amount > 0n).to.be.true;
615
+ expect(
616
+ secondCycleIntents[0].amount <= WEIGHTED_EXPECTED_DEFICIT_2ETH.toBigInt(),
617
+ 'Second cycle intent should not exceed the original deficit',
618
+ ).to.be.true;
619
+ });
620
+
621
+ it('uses bridge movements from different source chains before completion', async function () {
622
+ const context = await new TestRebalancerBuilder(
623
+ deploymentManager,
624
+ multiProvider,
625
+ )
626
+ .withStrategy(weightedStrategyConfig)
627
+ .withExecutionMode('execute')
628
+ .withInventoryConfig({
629
+ inventorySignerKey: ANVIL_USER_PRIVATE_KEY,
630
+ nativeDeployedAddresses,
631
+ })
632
+ .withMockExternalBridge(mockBridge)
633
+ .withInventorySignerBalances('SIGNER_WEIGHTED_BRIDGE_SOURCES')
634
+ .withBalances('INVENTORY_WEIGHTED_PARTIAL_SUPPLY')
635
+ .build();
636
+
637
+ await executeCycle(context);
638
+ await context.tracker.syncInventoryMovementActions({
639
+ [ExternalBridgeType.LiFi]: mockBridge,
640
+ });
641
+ await relayInProgressInventoryDeposits(
642
+ context,
643
+ localProviders,
644
+ multiProvider,
645
+ hyperlaneCore,
646
+ );
647
+
648
+ const cycle1ActiveIntents =
649
+ await context.tracker.getActiveRebalanceIntents();
650
+ expect(cycle1ActiveIntents.length).to.equal(1);
651
+ expect(cycle1ActiveIntents[0].destination).to.equal(DOMAIN_IDS.anvil3);
652
+ expect(cycle1ActiveIntents[0].amount).to.equal(
653
+ WEIGHTED_EXPECTED_DEFICIT_1_2ETH.toBigInt(),
654
+ );
655
+ const intentId = cycle1ActiveIntents[0].id;
656
+
657
+ const cycle1PartialIntents =
658
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
659
+ expect(cycle1PartialIntents.length).to.equal(1);
660
+ expect(cycle1PartialIntents[0].intent.id).to.equal(intentId);
661
+ expect(cycle1PartialIntents[0].remaining > 0n).to.be.true;
662
+ expect(
663
+ cycle1PartialIntents[0].completedAmount +
664
+ cycle1PartialIntents[0].remaining,
665
+ ).to.equal(WEIGHTED_EXPECTED_DEFICIT_1_2ETH.toBigInt());
666
+
667
+ let actions = await context.tracker.getActionsForIntent(intentId);
668
+ expect(actions.length).to.equal(1);
669
+ expect(
670
+ actions.filter((a) => a.type === 'inventory_deposit').length,
671
+ ).to.equal(1);
672
+ expect(
673
+ actions.filter((a) => a.type === 'inventory_movement').length,
674
+ ).to.equal(0);
675
+
676
+ await executeCycle(context);
677
+ await context.tracker.syncInventoryMovementActions({
678
+ [ExternalBridgeType.LiFi]: mockBridge,
679
+ });
680
+ await relayInProgressInventoryDeposits(
681
+ context,
682
+ localProviders,
683
+ multiProvider,
684
+ hyperlaneCore,
685
+ );
686
+
687
+ actions = await context.tracker.getActionsForIntent(intentId);
688
+ expect(actions.length).to.equal(3);
689
+
690
+ const movementActions = actions.filter(
691
+ (a) => a.type === 'inventory_movement',
692
+ );
693
+ expect(movementActions.length).to.equal(2);
694
+ const origins = new Set(movementActions.map((a) => a.origin));
695
+ expect(origins.has(DOMAIN_IDS.anvil1)).to.be.true;
696
+ expect(origins.has(DOMAIN_IDS.anvil2)).to.be.true;
697
+ movementActions.forEach((a) => {
698
+ expect(a.destination).to.equal(DOMAIN_IDS.anvil3);
699
+ expect(a.status).to.equal('complete');
700
+ });
701
+
702
+ const depositActions = actions.filter(
703
+ (a) => a.type === 'inventory_deposit',
704
+ );
705
+ expect(depositActions.length).to.equal(1);
706
+ const cycle2ActiveIntents =
707
+ await context.tracker.getActiveRebalanceIntents();
708
+ expect(cycle2ActiveIntents.length).to.equal(1);
709
+ const cycle2PartialIntents =
710
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
711
+ expect(cycle2PartialIntents.length).to.equal(1);
712
+
713
+ await executeCycle(context);
714
+ await context.tracker.syncInventoryMovementActions({
715
+ [ExternalBridgeType.LiFi]: mockBridge,
716
+ });
717
+ await relayInProgressInventoryDeposits(
718
+ context,
719
+ localProviders,
720
+ multiProvider,
721
+ hyperlaneCore,
722
+ );
723
+
724
+ const finalActiveIntents =
725
+ await context.tracker.getActiveRebalanceIntents();
726
+ expect(finalActiveIntents.length).to.equal(0);
727
+ const finalPartialIntents =
728
+ await context.tracker.getPartiallyFulfilledInventoryIntents();
729
+ expect(finalPartialIntents.length).to.equal(0);
730
+
731
+ const finalIntent = await context.tracker.getRebalanceIntent(intentId);
732
+ expect(finalIntent?.status).to.equal('complete');
733
+ });
734
+ });