@humanode-hyperlane/rebalancer 0.0.0-stage → 27.2.2-humanode.1

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,304 @@
1
+ import { expect } from 'chai';
2
+ import { BigNumber, providers } from 'ethers';
3
+
4
+ import {
5
+ HyperlaneCore,
6
+ MultiProvider,
7
+ snapshot,
8
+ } from '@humanode-hyperlane/sdk';
9
+
10
+ import {
11
+ RebalancerStrategyOptions,
12
+ type StrategyConfig,
13
+ } from '../config/types.js';
14
+
15
+ import {
16
+ DOMAIN_IDS,
17
+ type DeployedAddresses,
18
+ TEST_CHAINS,
19
+ } from './fixtures/routes.js';
20
+ import { getAllCollateralBalances } from './harness/BridgeSetup.js';
21
+ import { type LocalDeploymentContext } from './harness/BaseLocalDeploymentManager.js';
22
+ import { Erc20LocalDeploymentManager } from './harness/Erc20LocalDeploymentManager.js';
23
+ import { resetSnapshotsAndRefreshProviders } from './harness/SnapshotHelper.js';
24
+ import { getFirstMonitorEvent } from './harness/TestHelpers.js';
25
+ import { TestRebalancer } from './harness/TestRebalancer.js';
26
+ import { tryRelayMessage } from './harness/TransferHelper.js';
27
+
28
+ describe('WeightedStrategy E2E', function () {
29
+ this.timeout(300_000);
30
+
31
+ let deploymentManager: Erc20LocalDeploymentManager;
32
+ let multiProvider: MultiProvider;
33
+ let localProviders: Map<string, providers.JsonRpcProvider>;
34
+ let snapshotIds: Map<string, string>;
35
+ let hyperlaneCore: HyperlaneCore;
36
+ let deployedAddresses: DeployedAddresses;
37
+ let weightedStrategyConfig: StrategyConfig[];
38
+
39
+ before(async function () {
40
+ deploymentManager = new Erc20LocalDeploymentManager();
41
+ const ctx: LocalDeploymentContext<DeployedAddresses> =
42
+ await deploymentManager.start();
43
+ multiProvider = ctx.multiProvider;
44
+ localProviders = ctx.providers;
45
+ deployedAddresses = ctx.deployedAddresses;
46
+
47
+ const coreAddresses: Record<string, Record<string, string>> = {};
48
+ for (const chain of TEST_CHAINS) {
49
+ coreAddresses[chain] = {
50
+ mailbox: deployedAddresses.chains[chain].mailbox,
51
+ interchainSecurityModule: deployedAddresses.chains[chain].ism,
52
+ };
53
+ }
54
+ hyperlaneCore = HyperlaneCore.fromAddressesMap(
55
+ coreAddresses,
56
+ multiProvider,
57
+ );
58
+
59
+ weightedStrategyConfig = [
60
+ {
61
+ rebalanceStrategy: RebalancerStrategyOptions.Weighted,
62
+ chains: {
63
+ anvil1: {
64
+ weighted: { weight: 60n, tolerance: 5n },
65
+ bridge: deployedAddresses.bridgeRoute1.anvil1,
66
+ },
67
+ anvil2: {
68
+ weighted: { weight: 20n, tolerance: 5n },
69
+ bridge: deployedAddresses.bridgeRoute1.anvil2,
70
+ },
71
+ anvil3: {
72
+ weighted: { weight: 20n, tolerance: 5n },
73
+ bridge: deployedAddresses.bridgeRoute1.anvil3,
74
+ },
75
+ },
76
+ },
77
+ ];
78
+
79
+ snapshotIds = new Map();
80
+ for (const [chain, provider] of localProviders) {
81
+ snapshotIds.set(chain, await snapshot(provider));
82
+ }
83
+ });
84
+
85
+ afterEach(async function () {
86
+ await resetSnapshotsAndRefreshProviders({
87
+ localProviders,
88
+ multiProvider,
89
+ snapshotIds,
90
+ });
91
+ });
92
+
93
+ after(async function () {
94
+ if (deploymentManager) {
95
+ await deploymentManager.stop();
96
+ }
97
+ });
98
+
99
+ it('should propose rebalance routes when weights are unbalanced', async function () {
100
+ const context = await TestRebalancer.builder(
101
+ deploymentManager,
102
+ multiProvider,
103
+ )
104
+ .withStrategy(weightedStrategyConfig)
105
+ .withBalances('WEIGHTED_IMBALANCED')
106
+ .withExecutionMode('execute')
107
+ .build();
108
+
109
+ const monitor = context.createMonitor(0);
110
+ const event = await getFirstMonitorEvent(monitor);
111
+
112
+ await context.orchestrator.executeCycle(event);
113
+
114
+ // Assert: Strategy created rebalance intent for the imbalanced chain
115
+ const activeIntents = await context.tracker.getActiveRebalanceIntents();
116
+ expect(activeIntents.length).to.equal(1);
117
+ expect(activeIntents[0].origin).to.equal(DOMAIN_IDS.anvil1);
118
+ expect(activeIntents[0].destination).to.equal(DOMAIN_IDS.anvil3);
119
+ expect(activeIntents[0].amount).to.equal(1000000000n);
120
+ });
121
+
122
+ it('should not propose routes when within tolerance', async function () {
123
+ const context = await TestRebalancer.builder(
124
+ deploymentManager,
125
+ multiProvider,
126
+ )
127
+ .withStrategy(weightedStrategyConfig)
128
+ .withBalances('WEIGHTED_WITHIN_TOLERANCE')
129
+ .withExecutionMode('execute')
130
+ .build();
131
+
132
+ const monitor = context.createMonitor(0);
133
+ const event = await getFirstMonitorEvent(monitor);
134
+
135
+ await context.orchestrator.executeCycle(event);
136
+
137
+ // Assert: No intents created when within tolerance
138
+ const activeIntents = await context.tracker.getActiveRebalanceIntents();
139
+ expect(activeIntents.length).to.equal(0);
140
+ });
141
+
142
+ it('should execute full rebalance cycle with actual transfers', async function () {
143
+ const context = await TestRebalancer.builder(
144
+ deploymentManager,
145
+ multiProvider,
146
+ )
147
+ .withStrategy(weightedStrategyConfig)
148
+ .withBalances('WEIGHTED_IMBALANCED')
149
+ .withExecutionMode('execute')
150
+ .build();
151
+
152
+ const monitor = context.createMonitor(0);
153
+ const event = await getFirstMonitorEvent(monitor);
154
+ await context.orchestrator.executeCycle(event);
155
+
156
+ // Assert: Rebalance intent was created with correct fields
157
+ const activeIntents = await context.tracker.getActiveRebalanceIntents();
158
+ expect(activeIntents.length).to.equal(1);
159
+ expect(activeIntents[0].destination).to.equal(DOMAIN_IDS.anvil3);
160
+ expect(activeIntents[0].amount).to.equal(1000000000n);
161
+ expect(activeIntents[0].status).to.equal('in_progress');
162
+
163
+ // Assert: Rebalance action was created
164
+ const inProgressActions = await context.tracker.getInProgressActions();
165
+ expect(inProgressActions.length).to.equal(1);
166
+ expect(inProgressActions[0].intentId).to.equal(activeIntents[0].id);
167
+
168
+ // Assert: Ethereum balance decreased by 1000 USDC (rebalance amount)
169
+ const balancesAfterRebalance = await getAllCollateralBalances(
170
+ localProviders,
171
+ TEST_CHAINS,
172
+ deployedAddresses.monitoredRoute,
173
+ deployedAddresses.tokens,
174
+ );
175
+
176
+ // Initial: 7000 USDC - Rebalance: 1000 USDC = 6000 USDC
177
+ expect(
178
+ balancesAfterRebalance.anvil1.toString(),
179
+ 'anvil1 collateral should be 6000 USDC after rebalance',
180
+ ).to.equal('6000000000');
181
+
182
+ // Capture action details for relay
183
+ const actionToBase = inProgressActions[0];
184
+ const ethProvider = localProviders.get('anvil1')!;
185
+
186
+ // Relay the rebalance message to destination
187
+ expect(actionToBase.txHash, 'Action should have txHash').to.exist;
188
+ const rebalanceTxReceipt = await ethProvider.getTransactionReceipt(
189
+ actionToBase.txHash!,
190
+ );
191
+ const rebalanceRelayResult = await tryRelayMessage(
192
+ multiProvider,
193
+ hyperlaneCore,
194
+ {
195
+ dispatchTx: rebalanceTxReceipt,
196
+ messageId: actionToBase.messageId!,
197
+ origin: 'anvil1',
198
+ destination: 'anvil3',
199
+ },
200
+ );
201
+ expect(
202
+ rebalanceRelayResult.success,
203
+ `Rebalance relay should succeed: ${rebalanceRelayResult.error}`,
204
+ ).to.be.true;
205
+
206
+ const blockTags = await context.getConfirmedBlockTags();
207
+ await context.tracker.syncRebalanceActions(blockTags);
208
+
209
+ // Assert: Action is now complete
210
+ const completedAction = await context.tracker.getRebalanceAction(
211
+ actionToBase.id,
212
+ );
213
+ expect(completedAction!.status).to.equal('complete');
214
+
215
+ // Assert: Intent is now complete
216
+ const completedIntent = await context.tracker.getRebalanceIntent(
217
+ activeIntents[0].id,
218
+ );
219
+ expect(completedIntent!.status).to.equal('complete');
220
+
221
+ // Assert: No more in-progress actions
222
+ const remainingActions = await context.tracker.getInProgressActions();
223
+ expect(remainingActions.length).to.equal(0);
224
+ });
225
+
226
+ it('should handle stuck transfer and propose routes to destination', async function () {
227
+ // Build context with Weighted strategy
228
+ // Initial: eth=7000, arb=2000, base=1000 (total=10000)
229
+ // Target: eth=60% (6000), arb=20% (2000), base=20% (2000)
230
+ // Cycle 1 will create inflight eth→base for ~1000 USDC
231
+ const context = await TestRebalancer.builder(
232
+ deploymentManager,
233
+ multiProvider,
234
+ )
235
+ .withStrategy(weightedStrategyConfig)
236
+ .withBalances('WEIGHTED_IMBALANCED')
237
+ .withExecutionMode('execute')
238
+ .build();
239
+
240
+ // ===== CYCLE 1: Execute rebalance to create inflight eth→base =====
241
+ const monitor1 = context.createMonitor(0);
242
+ const event1 = await getFirstMonitorEvent(monitor1);
243
+ await context.orchestrator.executeCycle(event1);
244
+
245
+ const blockTags1 = await context.getConfirmedBlockTags();
246
+ await context.tracker.syncRebalanceActions(blockTags1);
247
+
248
+ const inflightAfterCycle1 = await context.tracker.getInProgressActions();
249
+ expect(
250
+ inflightAfterCycle1.length,
251
+ 'Cycle 1 should create inflight action',
252
+ ).to.be.greaterThan(0);
253
+
254
+ const inflightToBase = inflightAfterCycle1.find(
255
+ (a) =>
256
+ a.destination === DOMAIN_IDS.anvil3 && a.origin === DOMAIN_IDS.anvil1,
257
+ );
258
+ expect(inflightToBase, 'Should have inflight action eth→base').to.exist;
259
+
260
+ const inflightAmount = BigNumber.from(inflightToBase!.amount);
261
+ expect(inflightAmount.gt(0), 'Inflight amount should be positive').to.be
262
+ .true;
263
+
264
+ // ===== CYCLE 2: Execute again - should account for inflight =====
265
+ // Weighted now sees: base effective = current + inflight ≈ 2000 (target)
266
+ // Should create reduced amount or nothing to base
267
+ const monitor2 = context.createMonitor(0);
268
+ const event2 = await getFirstMonitorEvent(monitor2);
269
+ await context.orchestrator.executeCycle(event2);
270
+
271
+ const blockTags2 = await context.getConfirmedBlockTags();
272
+ await context.tracker.syncRebalanceActions(blockTags2);
273
+
274
+ // Check if new actions to base were created
275
+ const inProgressAfterCycle2 = await context.tracker.getInProgressActions();
276
+ const newActionsToBase = inProgressAfterCycle2.filter(
277
+ (a) =>
278
+ a.destination === DOMAIN_IDS.anvil3 &&
279
+ a.id !== inflightToBase!.id &&
280
+ a.status === 'in_progress',
281
+ );
282
+
283
+ if (newActionsToBase.length > 0) {
284
+ // If action was created, should be much smaller than original 1000 USDC
285
+ const proposedAmount = BigNumber.from(
286
+ newActionsToBase[0].amount,
287
+ ).toBigInt();
288
+ expect(
289
+ proposedAmount < 500000000n,
290
+ `Amount to base (${proposedAmount}) should be reduced accounting for inflight`,
291
+ ).to.be.true;
292
+ }
293
+ // If no new action to base, that's valid (within tolerance after inflight)
294
+
295
+ // Verify inflight still exists and action tracking is working
296
+ const finalInProgress = await context.tracker.getInProgressActions();
297
+ const inflightStillActive = finalInProgress.find(
298
+ (a) => a.id === inflightToBase!.id,
299
+ );
300
+ expect(inflightStillActive, 'Inflight action should still be tracked').to
301
+ .exist;
302
+ expect(inflightStillActive!.status).to.equal('in_progress');
303
+ });
304
+ });
@@ -0,0 +1,394 @@
1
+ import { expect } from 'chai';
2
+ import { pino } from 'pino';
3
+ import Sinon from 'sinon';
4
+
5
+ import { type IRegistry, RegistryType } from '@humanode-hyperlane/registry';
6
+ import {
7
+ MultiProtocolProvider,
8
+ MultiProvider,
9
+ TokenStandard,
10
+ type WarpCoreConfig,
11
+ } from '@humanode-hyperlane/sdk';
12
+ import { ProtocolType, assert } from '@humanode-hyperlane/utils';
13
+
14
+ import type { RebalancerConfig } from '../config/RebalancerConfig.js';
15
+ import {
16
+ ExecutionType,
17
+ DEFAULT_INTENT_TTL_MS,
18
+ RebalancerStrategyOptions,
19
+ } from '../config/types.js';
20
+ import { TEST_ADDRESSES } from '../test/helpers.js';
21
+
22
+ import { RebalancerContextFactory } from './RebalancerContextFactory.js';
23
+
24
+ const testLogger = pino({ level: 'silent' });
25
+
26
+ function createMockRegistry(): IRegistry {
27
+ return {
28
+ type: RegistryType.Partial,
29
+ uri: 'mock://registry',
30
+ getUri: Sinon.stub().returns('mock://registry'),
31
+ listRegistryContent: Sinon.stub().resolves({
32
+ chains: {},
33
+ deployments: { warpRoutes: {}, warpDeployConfig: {} },
34
+ }),
35
+ getChains: Sinon.stub().resolves([]),
36
+ getMetadata: Sinon.stub().resolves({}),
37
+ getChainMetadata: Sinon.stub().resolves(null),
38
+ getAddresses: Sinon.stub().resolves({
39
+ ethereum: { mailbox: TEST_ADDRESSES.ethereum },
40
+ arbitrum: { mailbox: TEST_ADDRESSES.arbitrum },
41
+ paradex: { mailbox: TEST_ADDRESSES.polygon },
42
+ }),
43
+ getChainAddresses: Sinon.stub().resolves({
44
+ mailbox: TEST_ADDRESSES.ethereum,
45
+ }),
46
+ getChainLogoUri: Sinon.stub().resolves(null),
47
+ addChain: Sinon.stub().resolves(),
48
+ updateChain: Sinon.stub().resolves(),
49
+ removeChain: Sinon.stub().resolves(),
50
+ getWarpRoute: Sinon.stub().resolves(null),
51
+ getWarpRoutes: Sinon.stub().resolves({}),
52
+ addWarpRoute: Sinon.stub().resolves(),
53
+ addWarpRouteConfig: Sinon.stub().resolves(),
54
+ getWarpDeployConfig: Sinon.stub().resolves({}),
55
+ getWarpDeployConfigs: Sinon.stub().resolves({}),
56
+ merge: Sinon.stub().returnsThis(),
57
+ };
58
+ }
59
+
60
+ function createMockConfig(): RebalancerConfig {
61
+ return {
62
+ warpRouteId: 'USDC/paradex',
63
+ strategyConfig: [
64
+ {
65
+ rebalanceStrategy: RebalancerStrategyOptions.Weighted,
66
+ chains: {
67
+ ethereum: {
68
+ bridge: TEST_ADDRESSES.bridge,
69
+ bridgeMinAcceptedAmount: 0,
70
+ weighted: { weight: 50n, tolerance: 10n },
71
+ },
72
+ arbitrum: {
73
+ bridge: TEST_ADDRESSES.bridge,
74
+ bridgeMinAcceptedAmount: 0,
75
+ weighted: { weight: 50n, tolerance: 10n },
76
+ },
77
+ },
78
+ },
79
+ ],
80
+ intentTTL: DEFAULT_INTENT_TTL_MS,
81
+ } as RebalancerConfig;
82
+ }
83
+
84
+ function createMockMpp() {
85
+ const mpp = Sinon.createStubInstance(MultiProtocolProvider);
86
+ mpp.extendChainMetadata.returnsThis();
87
+ return mpp;
88
+ }
89
+
90
+ function createToken(
91
+ chainName: string,
92
+ addressOrDenom: string,
93
+ standard: TokenStandard,
94
+ ) {
95
+ return {
96
+ chainName,
97
+ addressOrDenom,
98
+ standard,
99
+ decimals: 6,
100
+ symbol: 'USDC',
101
+ name: 'USDC',
102
+ };
103
+ }
104
+
105
+ interface ChainDef {
106
+ name: string;
107
+ protocol: ProtocolType;
108
+ }
109
+
110
+ function createMockMultiProvider(chains: ChainDef[]) {
111
+ const protocolMap = Object.fromEntries(
112
+ chains.map((c) => [c.name, c.protocol]),
113
+ );
114
+
115
+ const multiProvider = Sinon.createStubInstance(MultiProvider);
116
+ multiProvider.getProtocol.callsFake((chain) => {
117
+ const protocol = protocolMap[String(chain)];
118
+ assert(protocol, `No protocol in mock for chain ${chain}`);
119
+ return protocol;
120
+ });
121
+
122
+ return { multiProvider };
123
+ }
124
+
125
+ async function createFactory(
126
+ config: RebalancerConfig,
127
+ multiProvider: MultiProvider,
128
+ warpCoreConfig: WarpCoreConfig,
129
+ ) {
130
+ return RebalancerContextFactory.create(
131
+ config,
132
+ multiProvider,
133
+ createMockMpp(),
134
+ createMockRegistry(),
135
+ testLogger,
136
+ undefined,
137
+ warpCoreConfig,
138
+ );
139
+ }
140
+
141
+ async function callCreate(
142
+ multiProvider: MultiProvider,
143
+ warpCoreConfig: WarpCoreConfig,
144
+ ) {
145
+ await createFactory(createMockConfig(), multiProvider, warpCoreConfig);
146
+ }
147
+
148
+ describe('RebalancerContextFactory', () => {
149
+ let sandbox: Sinon.SinonSandbox;
150
+
151
+ beforeEach(() => {
152
+ sandbox = Sinon.createSandbox();
153
+ });
154
+
155
+ afterEach(() => {
156
+ sandbox.restore();
157
+ });
158
+
159
+ describe('create() — non-EVM chain handling', () => {
160
+ it('should skip provider initialization for StarkNet chains', async () => {
161
+ const { multiProvider } = createMockMultiProvider([
162
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
163
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
164
+ { name: 'paradex', protocol: ProtocolType.Starknet },
165
+ ]);
166
+
167
+ await callCreate(multiProvider, {
168
+ tokens: [
169
+ createToken(
170
+ 'ethereum',
171
+ TEST_ADDRESSES.ethereum,
172
+ TokenStandard.EvmHypCollateral,
173
+ ),
174
+ createToken(
175
+ 'arbitrum',
176
+ TEST_ADDRESSES.arbitrum,
177
+ TokenStandard.EvmHypSynthetic,
178
+ ),
179
+ createToken(
180
+ 'paradex',
181
+ '0xparadex',
182
+ TokenStandard.StarknetHypSynthetic,
183
+ ),
184
+ ],
185
+ });
186
+
187
+ expect(multiProvider.getProvider.callCount).to.equal(2);
188
+ const providerChains = multiProvider.getProvider
189
+ .getCalls()
190
+ .map((c) => c.args[0]);
191
+ expect(providerChains).to.include('ethereum');
192
+ expect(providerChains).to.include('arbitrum');
193
+ expect(providerChains).to.not.include('paradex');
194
+ });
195
+
196
+ it('should skip provider initialization for Sealevel chains', async () => {
197
+ const { multiProvider } = createMockMultiProvider([
198
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
199
+ { name: 'solana', protocol: ProtocolType.Sealevel },
200
+ ]);
201
+
202
+ await callCreate(multiProvider, {
203
+ tokens: [
204
+ createToken(
205
+ 'ethereum',
206
+ TEST_ADDRESSES.ethereum,
207
+ TokenStandard.EvmHypCollateral,
208
+ ),
209
+ createToken(
210
+ 'solana',
211
+ 'SolToken111',
212
+ TokenStandard.SealevelHypSynthetic,
213
+ ),
214
+ ],
215
+ });
216
+
217
+ expect(multiProvider.getProvider.callCount).to.equal(1);
218
+ expect(multiProvider.getProvider.firstCall.args[0]).to.equal('ethereum');
219
+ });
220
+
221
+ it('should call getProvider for all chains when all are EVM', async () => {
222
+ const { multiProvider } = createMockMultiProvider([
223
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
224
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
225
+ ]);
226
+
227
+ await callCreate(multiProvider, {
228
+ tokens: [
229
+ createToken(
230
+ 'ethereum',
231
+ TEST_ADDRESSES.ethereum,
232
+ TokenStandard.EvmHypCollateral,
233
+ ),
234
+ createToken(
235
+ 'arbitrum',
236
+ TEST_ADDRESSES.arbitrum,
237
+ TokenStandard.EvmHypSynthetic,
238
+ ),
239
+ ],
240
+ });
241
+
242
+ expect(multiProvider.getProvider.callCount).to.equal(2);
243
+ const providerChains = multiProvider.getProvider
244
+ .getCalls()
245
+ .map((c) => c.args[0]);
246
+ expect(providerChains).to.include('ethereum');
247
+ expect(providerChains).to.include('arbitrum');
248
+ });
249
+
250
+ it('should fail early when inventory override origin protocol signer key is missing', async () => {
251
+ const sealevelChain = 'solana';
252
+ const evmChain = 'ethereum';
253
+ const { multiProvider } = createMockMultiProvider([
254
+ { name: evmChain, protocol: ProtocolType.Ethereum },
255
+ { name: sealevelChain, protocol: ProtocolType.Sealevel },
256
+ ]);
257
+
258
+ const config = {
259
+ warpRouteId: 'USDC/mixed-route',
260
+ strategyConfig: [
261
+ {
262
+ rebalanceStrategy: RebalancerStrategyOptions.Weighted,
263
+ chains: {
264
+ [sealevelChain]: {
265
+ bridge: TEST_ADDRESSES.bridge,
266
+ weighted: { weight: 50n, tolerance: 10n },
267
+ override: {
268
+ [evmChain]: {
269
+ executionType: ExecutionType.Inventory,
270
+ },
271
+ },
272
+ },
273
+ [evmChain]: {
274
+ bridge: TEST_ADDRESSES.bridge,
275
+ weighted: { weight: 50n, tolerance: 10n },
276
+ },
277
+ },
278
+ },
279
+ ],
280
+ inventorySigners: {
281
+ [ProtocolType.Ethereum]: {
282
+ address: TEST_ADDRESSES.ethereum,
283
+ key: '0xabc123',
284
+ },
285
+ },
286
+ intentTTL: DEFAULT_INTENT_TTL_MS,
287
+ } as RebalancerConfig;
288
+
289
+ const factory = await createFactory(config, multiProvider, {
290
+ tokens: [
291
+ createToken(
292
+ evmChain,
293
+ TEST_ADDRESSES.ethereum,
294
+ TokenStandard.EvmHypSynthetic,
295
+ ),
296
+ createToken(
297
+ sealevelChain,
298
+ 'SolToken1111111111111111111111111111111111111',
299
+ TokenStandard.SealevelHypCollateral,
300
+ ),
301
+ ],
302
+ });
303
+
304
+ const getChainMetadataStub = factory.getWarpCore().multiProvider
305
+ .getChainMetadata as Sinon.SinonStub;
306
+ getChainMetadataStub.callsFake((chainName: string) => ({
307
+ protocol:
308
+ chainName === sealevelChain
309
+ ? ProtocolType.Sealevel
310
+ : ProtocolType.Ethereum,
311
+ }));
312
+
313
+ await expect(
314
+ (factory as any).createInventoryRebalancerAndConfig({} as any, {}),
315
+ ).to.be.rejectedWith(
316
+ `Missing inventory signer key for protocol ${ProtocolType.Sealevel}`,
317
+ );
318
+ });
319
+
320
+ it('should fail early when inventory chain uses unsupported protocol', async () => {
321
+ const cosmosChain = 'cosmoshub';
322
+ const evmChain = 'ethereum';
323
+ const { multiProvider } = createMockMultiProvider([
324
+ { name: evmChain, protocol: ProtocolType.Ethereum },
325
+ { name: cosmosChain, protocol: ProtocolType.Cosmos },
326
+ ]);
327
+
328
+ const config = {
329
+ warpRouteId: 'USDC/cosmos-route',
330
+ strategyConfig: [
331
+ {
332
+ rebalanceStrategy: RebalancerStrategyOptions.Weighted,
333
+ chains: {
334
+ [cosmosChain]: {
335
+ bridge: TEST_ADDRESSES.bridge,
336
+ weighted: { weight: 50n, tolerance: 10n },
337
+ override: {
338
+ [evmChain]: {
339
+ executionType: ExecutionType.Inventory,
340
+ },
341
+ },
342
+ },
343
+ [evmChain]: {
344
+ bridge: TEST_ADDRESSES.bridge,
345
+ weighted: { weight: 50n, tolerance: 10n },
346
+ },
347
+ },
348
+ },
349
+ ],
350
+ inventorySigners: {
351
+ [ProtocolType.Ethereum]: {
352
+ address: TEST_ADDRESSES.ethereum,
353
+ key: '0xabc123',
354
+ },
355
+ [ProtocolType.Cosmos]: {
356
+ address: 'cosmos1qypqxpq9qcrsszg2pvxq6rs0zqg3yyc5lzv7xu',
357
+ key: 'cosmos_key',
358
+ },
359
+ },
360
+ intentTTL: DEFAULT_INTENT_TTL_MS,
361
+ } as RebalancerConfig;
362
+
363
+ const factory = await createFactory(config, multiProvider, {
364
+ tokens: [
365
+ createToken(
366
+ evmChain,
367
+ TEST_ADDRESSES.ethereum,
368
+ TokenStandard.EvmHypSynthetic,
369
+ ),
370
+ createToken(
371
+ cosmosChain,
372
+ 'cosmos1token',
373
+ TokenStandard.EvmHypSynthetic,
374
+ ),
375
+ ],
376
+ });
377
+
378
+ const getChainMetadataStub = factory.getWarpCore().multiProvider
379
+ .getChainMetadata as Sinon.SinonStub;
380
+ getChainMetadataStub.callsFake((chainName: string) => ({
381
+ protocol:
382
+ chainName === cosmosChain
383
+ ? ProtocolType.Cosmos
384
+ : ProtocolType.Ethereum,
385
+ }));
386
+
387
+ await expect(
388
+ (factory as any).createInventoryRebalancerAndConfig({} as any, {}),
389
+ ).to.be.rejectedWith(
390
+ `Inventory rebalancing does not support protocol '${ProtocolType.Cosmos}'`,
391
+ );
392
+ });
393
+ });
394
+ });