@humanode-hyperlane/rebalancer 27.2.2 → 1029.1.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 (295) hide show
  1. package/dist/bridges/LiFiBridge.d.ts +3 -3
  2. package/dist/bridges/LiFiBridge.d.ts.map +1 -1
  3. package/dist/bridges/LiFiBridge.js +66 -55
  4. package/dist/bridges/LiFiBridge.js.map +1 -1
  5. package/dist/bridges/LiFiBridge.test.js +213 -0
  6. package/dist/bridges/LiFiBridge.test.js.map +1 -1
  7. package/dist/config/RebalancerConfig.d.ts +4 -3
  8. package/dist/config/RebalancerConfig.d.ts.map +1 -1
  9. package/dist/config/RebalancerConfig.js +7 -5
  10. package/dist/config/RebalancerConfig.js.map +1 -1
  11. package/dist/config/RebalancerConfig.test.js +278 -2
  12. package/dist/config/RebalancerConfig.test.js.map +1 -1
  13. package/dist/config/types.d.ts +707 -2664
  14. package/dist/config/types.d.ts.map +1 -1
  15. package/dist/config/types.js +62 -7
  16. package/dist/config/types.js.map +1 -1
  17. package/dist/core/InventoryRebalancer.d.ts +13 -19
  18. package/dist/core/InventoryRebalancer.d.ts.map +1 -1
  19. package/dist/core/InventoryRebalancer.js +404 -276
  20. package/dist/core/InventoryRebalancer.js.map +1 -1
  21. package/dist/core/InventoryRebalancer.test.js +814 -25
  22. package/dist/core/InventoryRebalancer.test.js.map +1 -1
  23. package/dist/core/Rebalancer.d.ts.map +1 -1
  24. package/dist/core/Rebalancer.js +12 -6
  25. package/dist/core/Rebalancer.js.map +1 -1
  26. package/dist/core/Rebalancer.test.js +51 -0
  27. package/dist/core/Rebalancer.test.js.map +1 -1
  28. package/dist/core/RebalancerOrchestrator.d.ts.map +1 -1
  29. package/dist/core/RebalancerOrchestrator.test.js +0 -1
  30. package/dist/core/RebalancerOrchestrator.test.js.map +1 -1
  31. package/dist/core/RebalancerService.d.ts.map +1 -1
  32. package/dist/core/RebalancerService.js +3 -2
  33. package/dist/core/RebalancerService.js.map +1 -1
  34. package/dist/core/RebalancerService.test.js +24 -0
  35. package/dist/core/RebalancerService.test.js.map +1 -1
  36. package/dist/e2e/fixtures/routes.d.ts +3 -3
  37. package/dist/e2e/fixtures/routes.d.ts.map +1 -1
  38. package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts.map +1 -1
  39. package/dist/e2e/harness/BaseLocalDeploymentManager.js +3 -2
  40. package/dist/e2e/harness/BaseLocalDeploymentManager.js.map +1 -1
  41. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts.map +1 -1
  42. package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js.map +1 -1
  43. package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts.map +1 -1
  44. package/dist/e2e/harness/ForkIndexer.d.ts.map +1 -1
  45. package/dist/e2e/harness/ForkIndexer.js.map +1 -1
  46. package/dist/e2e/harness/LocalProvider.d.ts +3 -0
  47. package/dist/e2e/harness/LocalProvider.d.ts.map +1 -0
  48. package/dist/e2e/harness/LocalProvider.js +9 -0
  49. package/dist/e2e/harness/LocalProvider.js.map +1 -0
  50. package/dist/e2e/harness/LocalProvider.test.d.ts +2 -0
  51. package/dist/e2e/harness/LocalProvider.test.d.ts.map +1 -0
  52. package/dist/e2e/harness/LocalProvider.test.js +14 -0
  53. package/dist/e2e/harness/LocalProvider.test.js.map +1 -0
  54. package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts.map +1 -1
  55. package/dist/e2e/harness/MixedLocalDeploymentManager.js.map +1 -1
  56. package/dist/e2e/harness/MockExplorerClient.d.ts.map +1 -1
  57. package/dist/e2e/harness/MockExplorerClient.js.map +1 -1
  58. package/dist/e2e/harness/MockExternalBridge.d.ts.map +1 -1
  59. package/dist/e2e/harness/MockExternalBridge.js.map +1 -1
  60. package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts.map +1 -1
  61. package/dist/e2e/harness/NativeLocalDeploymentManager.js +2 -1
  62. package/dist/e2e/harness/NativeLocalDeploymentManager.js.map +1 -1
  63. package/dist/e2e/harness/SnapshotHelper.d.ts.map +1 -1
  64. package/dist/e2e/harness/SnapshotHelper.js +3 -5
  65. package/dist/e2e/harness/SnapshotHelper.js.map +1 -1
  66. package/dist/e2e/harness/TestHelpers.js +1 -2
  67. package/dist/e2e/harness/TestHelpers.js.map +1 -1
  68. package/dist/e2e/harness/TestRebalancer.d.ts +5 -1
  69. package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -1
  70. package/dist/e2e/harness/TestRebalancer.js +14 -4
  71. package/dist/e2e/harness/TestRebalancer.js.map +1 -1
  72. package/dist/e2e/relayer-denylist.e2e-test.d.ts +2 -0
  73. package/dist/e2e/relayer-denylist.e2e-test.d.ts.map +1 -0
  74. package/dist/e2e/relayer-denylist.e2e-test.js +388 -0
  75. package/dist/e2e/relayer-denylist.e2e-test.js.map +1 -0
  76. package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
  77. package/dist/factories/RebalancerContextFactory.js +61 -31
  78. package/dist/factories/RebalancerContextFactory.js.map +1 -1
  79. package/dist/factories/RebalancerContextFactory.test.js +336 -5
  80. package/dist/factories/RebalancerContextFactory.test.js.map +1 -1
  81. package/dist/index.d.ts +2 -2
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +1 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/interfaces/IRebalancer.d.ts +4 -2
  86. package/dist/interfaces/IRebalancer.d.ts.map +1 -1
  87. package/dist/metrics/Metrics.d.ts.map +1 -1
  88. package/dist/metrics/Metrics.js +1 -1
  89. package/dist/metrics/Metrics.js.map +1 -1
  90. package/dist/metrics/PriceGetter.d.ts +1 -0
  91. package/dist/metrics/PriceGetter.d.ts.map +1 -1
  92. package/dist/metrics/PriceGetter.js +14 -4
  93. package/dist/metrics/PriceGetter.js.map +1 -1
  94. package/dist/metrics/PriceGetter.test.d.ts +2 -0
  95. package/dist/metrics/PriceGetter.test.d.ts.map +1 -0
  96. package/dist/metrics/PriceGetter.test.js +84 -0
  97. package/dist/metrics/PriceGetter.test.js.map +1 -0
  98. package/dist/metrics/scripts/metrics.d.ts +4 -4
  99. package/dist/monitor/Monitor.d.ts +1 -0
  100. package/dist/monitor/Monitor.d.ts.map +1 -1
  101. package/dist/monitor/Monitor.js +55 -46
  102. package/dist/monitor/Monitor.js.map +1 -1
  103. package/dist/monitor/Monitor.test.d.ts +2 -0
  104. package/dist/monitor/Monitor.test.d.ts.map +1 -0
  105. package/dist/monitor/Monitor.test.js +346 -0
  106. package/dist/monitor/Monitor.test.js.map +1 -0
  107. package/dist/service.d.ts +1 -1
  108. package/dist/service.d.ts.map +1 -1
  109. package/dist/service.js +9 -5
  110. package/dist/service.js.map +1 -1
  111. package/dist/strategy/BaseStrategy.d.ts.map +1 -1
  112. package/dist/strategy/BaseStrategy.js +13 -11
  113. package/dist/strategy/BaseStrategy.js.map +1 -1
  114. package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -1
  115. package/dist/strategy/CollateralDeficitStrategy.js +2 -2
  116. package/dist/strategy/CollateralDeficitStrategy.js.map +1 -1
  117. package/dist/strategy/CompositeStrategy.d.ts.map +1 -1
  118. package/dist/strategy/CompositeStrategy.js.map +1 -1
  119. package/dist/strategy/CompositeStrategy.test.js.map +1 -1
  120. package/dist/strategy/MinAmountStrategy.d.ts +1 -0
  121. package/dist/strategy/MinAmountStrategy.d.ts.map +1 -1
  122. package/dist/strategy/MinAmountStrategy.js +12 -8
  123. package/dist/strategy/MinAmountStrategy.js.map +1 -1
  124. package/dist/strategy/MinAmountStrategy.test.js +189 -2
  125. package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
  126. package/dist/strategy/StrategyFactory.d.ts.map +1 -1
  127. package/dist/strategy/StrategyFactory.js.map +1 -1
  128. package/dist/strategy/WeightedStrategy.d.ts.map +1 -1
  129. package/dist/test/helpers.d.ts +11 -3
  130. package/dist/test/helpers.d.ts.map +1 -1
  131. package/dist/test/helpers.js +9 -11
  132. package/dist/test/helpers.js.map +1 -1
  133. package/dist/test/lifiMocks.d.ts +6 -6
  134. package/dist/test/lifiMocks.d.ts.map +1 -1
  135. package/dist/test/lifiMocks.js +5 -2
  136. package/dist/test/lifiMocks.js.map +1 -1
  137. package/dist/test/pendingTransferMiddlewareMocks.d.ts +17 -0
  138. package/dist/test/pendingTransferMiddlewareMocks.d.ts.map +1 -0
  139. package/dist/test/pendingTransferMiddlewareMocks.js +43 -0
  140. package/dist/test/pendingTransferMiddlewareMocks.js.map +1 -0
  141. package/dist/tracking/ActionTracker.d.ts +4 -0
  142. package/dist/tracking/ActionTracker.d.ts.map +1 -1
  143. package/dist/tracking/ActionTracker.js +76 -9
  144. package/dist/tracking/ActionTracker.js.map +1 -1
  145. package/dist/tracking/ActionTracker.test.js +418 -1
  146. package/dist/tracking/ActionTracker.test.js.map +1 -1
  147. package/dist/tracking/IActionTracker.d.ts +4 -2
  148. package/dist/tracking/IActionTracker.d.ts.map +1 -1
  149. package/dist/tracking/InflightContextAdapter.d.ts.map +1 -1
  150. package/dist/tracking/InflightContextAdapter.js.map +1 -1
  151. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts +64 -0
  152. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts.map +1 -0
  153. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js +474 -0
  154. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js.map +1 -0
  155. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts +2 -0
  156. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts.map +1 -0
  157. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js +1168 -0
  158. package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js.map +1 -0
  159. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts +61 -0
  160. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts.map +1 -0
  161. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js +160 -0
  162. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js.map +1 -0
  163. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts +2 -0
  164. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts.map +1 -0
  165. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js +369 -0
  166. package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js.map +1 -0
  167. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts +60 -0
  168. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts.map +1 -0
  169. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js +288 -0
  170. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js.map +1 -0
  171. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts +2 -0
  172. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts.map +1 -0
  173. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js +606 -0
  174. package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js.map +1 -0
  175. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts +25 -0
  176. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts.map +1 -0
  177. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js +41 -0
  178. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js.map +1 -0
  179. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts +2 -0
  180. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts.map +1 -0
  181. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js +141 -0
  182. package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js.map +1 -0
  183. package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts +12 -0
  184. package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts.map +1 -0
  185. package/dist/tracking/pendingTransferMiddlewares/matchBody.js +29 -0
  186. package/dist/tracking/pendingTransferMiddlewares/matchBody.js.map +1 -0
  187. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts +59 -0
  188. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts.map +1 -0
  189. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js +661 -0
  190. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js.map +1 -0
  191. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts +2 -0
  192. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts.map +1 -0
  193. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js +1093 -0
  194. package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js.map +1 -0
  195. package/dist/tracking/pendingTransferMiddlewares/types.d.ts +2 -0
  196. package/dist/tracking/pendingTransferMiddlewares/types.d.ts.map +1 -0
  197. package/dist/tracking/pendingTransferMiddlewares/types.js +4 -0
  198. package/dist/tracking/pendingTransferMiddlewares/types.js.map +1 -0
  199. package/dist/tracking/store/InMemoryStore.d.ts.map +1 -1
  200. package/dist/utils/ExplorerClient.d.ts +1 -0
  201. package/dist/utils/ExplorerClient.d.ts.map +1 -1
  202. package/dist/utils/ExplorerClient.js +8 -3
  203. package/dist/utils/ExplorerClient.js.map +1 -1
  204. package/dist/utils/ExplorerClient.test.js +25 -0
  205. package/dist/utils/ExplorerClient.test.js.map +1 -1
  206. package/dist/utils/balanceUtils.d.ts +7 -1
  207. package/dist/utils/balanceUtils.d.ts.map +1 -1
  208. package/dist/utils/balanceUtils.js +39 -1
  209. package/dist/utils/balanceUtils.js.map +1 -1
  210. package/dist/utils/balanceUtils.test.js +55 -1
  211. package/dist/utils/balanceUtils.test.js.map +1 -1
  212. package/dist/utils/blockTag.d.ts +5 -4
  213. package/dist/utils/blockTag.d.ts.map +1 -1
  214. package/dist/utils/blockTag.js +26 -10
  215. package/dist/utils/blockTag.js.map +1 -1
  216. package/dist/utils/blockTag.test.d.ts +2 -0
  217. package/dist/utils/blockTag.test.d.ts.map +1 -0
  218. package/dist/utils/blockTag.test.js +132 -0
  219. package/dist/utils/blockTag.test.js.map +1 -0
  220. package/dist/utils/bridgeUtils.js.map +1 -1
  221. package/dist/utils/errors.d.ts.map +1 -1
  222. package/dist/utils/gasEstimation.d.ts +2 -1
  223. package/dist/utils/gasEstimation.d.ts.map +1 -1
  224. package/dist/utils/gasEstimation.js +16 -13
  225. package/dist/utils/gasEstimation.js.map +1 -1
  226. package/dist/utils/gasEstimation.test.d.ts +2 -0
  227. package/dist/utils/gasEstimation.test.d.ts.map +1 -0
  228. package/dist/utils/gasEstimation.test.js +104 -0
  229. package/dist/utils/gasEstimation.test.js.map +1 -0
  230. package/dist/utils/tokenUtils.d.ts.map +1 -1
  231. package/dist/utils/tokenUtils.js +5 -2
  232. package/dist/utils/tokenUtils.js.map +1 -1
  233. package/package.json +23 -22
  234. package/src/bridges/LiFiBridge.test.ts +270 -0
  235. package/src/bridges/LiFiBridge.ts +90 -71
  236. package/src/config/RebalancerConfig.test.ts +315 -1
  237. package/src/config/RebalancerConfig.ts +6 -3
  238. package/src/config/types.ts +98 -8
  239. package/src/core/InventoryRebalancer.test.ts +1092 -38
  240. package/src/core/InventoryRebalancer.ts +584 -351
  241. package/src/core/Rebalancer.test.ts +84 -0
  242. package/src/core/Rebalancer.ts +22 -6
  243. package/src/core/RebalancerOrchestrator.test.ts +0 -1
  244. package/src/core/RebalancerService.test.ts +35 -0
  245. package/src/core/RebalancerService.ts +3 -2
  246. package/src/e2e/harness/BaseLocalDeploymentManager.ts +3 -1
  247. package/src/e2e/harness/LocalProvider.test.ts +16 -0
  248. package/src/e2e/harness/LocalProvider.ts +10 -0
  249. package/src/e2e/harness/NativeLocalDeploymentManager.ts +2 -1
  250. package/src/e2e/harness/SnapshotHelper.ts +2 -5
  251. package/src/e2e/harness/TestHelpers.ts +3 -3
  252. package/src/e2e/harness/TestRebalancer.ts +21 -1
  253. package/src/e2e/relayer-denylist.e2e-test.ts +558 -0
  254. package/src/factories/RebalancerContextFactory.test.ts +489 -8
  255. package/src/factories/RebalancerContextFactory.ts +86 -36
  256. package/src/index.ts +2 -0
  257. package/src/interfaces/IRebalancer.ts +4 -1
  258. package/src/metrics/Metrics.ts +1 -0
  259. package/src/metrics/PriceGetter.test.ts +113 -0
  260. package/src/metrics/PriceGetter.ts +18 -3
  261. package/src/monitor/Monitor.test.ts +408 -0
  262. package/src/monitor/Monitor.ts +123 -97
  263. package/src/service.ts +14 -8
  264. package/src/strategy/BaseStrategy.ts +18 -15
  265. package/src/strategy/CollateralDeficitStrategy.ts +4 -3
  266. package/src/strategy/MinAmountStrategy.test.ts +238 -2
  267. package/src/strategy/MinAmountStrategy.ts +29 -17
  268. package/src/test/helpers.ts +13 -12
  269. package/src/test/lifiMocks.ts +5 -2
  270. package/src/test/pendingTransferMiddlewareMocks.ts +65 -0
  271. package/src/tracking/ActionTracker.test.ts +635 -3
  272. package/src/tracking/ActionTracker.ts +92 -12
  273. package/src/tracking/IActionTracker.ts +4 -2
  274. package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.ts +1693 -0
  275. package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.ts +784 -0
  276. package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.ts +554 -0
  277. package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.ts +233 -0
  278. package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.ts +894 -0
  279. package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.ts +404 -0
  280. package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.ts +205 -0
  281. package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.ts +89 -0
  282. package/src/tracking/pendingTransferMiddlewares/fixtures/mainnet-denylist.json +3556 -0
  283. package/src/tracking/pendingTransferMiddlewares/matchBody.ts +43 -0
  284. package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.ts +1220 -0
  285. package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.ts +934 -0
  286. package/src/tracking/pendingTransferMiddlewares/types.ts +3 -0
  287. package/src/utils/ExplorerClient.test.ts +42 -0
  288. package/src/utils/ExplorerClient.ts +14 -3
  289. package/src/utils/balanceUtils.test.ts +87 -1
  290. package/src/utils/balanceUtils.ts +73 -2
  291. package/src/utils/blockTag.test.ts +173 -0
  292. package/src/utils/blockTag.ts +35 -15
  293. package/src/utils/gasEstimation.test.ts +192 -0
  294. package/src/utils/gasEstimation.ts +17 -11
  295. package/src/utils/tokenUtils.ts +5 -2
@@ -1,9 +1,17 @@
1
1
  import { expect } from 'chai';
2
+ import { ethers, type providers } from 'ethers';
2
3
  import { pino } from 'pino';
3
4
  import Sinon from 'sinon';
4
5
 
6
+ import {
7
+ BlacklistIsm__factory,
8
+ Mailbox__factory,
9
+ } from '@humanode-hyperlane/core';
5
10
  import { type IRegistry, RegistryType } from '@humanode-hyperlane/registry';
6
11
  import {
12
+ EvmIsmReader,
13
+ IsmType,
14
+ MultiProtocolCore,
7
15
  MultiProtocolProvider,
8
16
  MultiProvider,
9
17
  TokenStandard,
@@ -11,13 +19,18 @@ import {
11
19
  } from '@humanode-hyperlane/sdk';
12
20
  import { ProtocolType, assert } from '@humanode-hyperlane/utils';
13
21
 
14
- import type { RebalancerConfig } from '../config/RebalancerConfig.js';
22
+ import { RebalancerConfig } from '../config/RebalancerConfig.js';
15
23
  import {
16
24
  ExecutionType,
17
25
  DEFAULT_INTENT_TTL_MS,
26
+ type PendingTransferMiddlewareConfig,
27
+ PendingTransferMiddlewareType,
18
28
  RebalancerStrategyOptions,
19
29
  } from '../config/types.js';
20
30
  import { TEST_ADDRESSES } from '../test/helpers.js';
31
+ import { ActionTracker } from '../tracking/ActionTracker.js';
32
+ import { BlacklistIsmMiddleware } from '../tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js';
33
+ import type { IExplorerClient } from '../utils/ExplorerClient.js';
21
34
 
22
35
  import { RebalancerContextFactory } from './RebalancerContextFactory.js';
23
36
 
@@ -156,6 +169,222 @@ describe('RebalancerContextFactory', () => {
156
169
  sandbox.restore();
157
170
  });
158
171
 
172
+ describe('external bridge initialization', () => {
173
+ async function factoryWithBridges(
174
+ externalBridges?: RebalancerConfig['externalBridges'],
175
+ ) {
176
+ const { multiProvider } = createMockMultiProvider([
177
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
178
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
179
+ ]);
180
+ return createFactory(
181
+ { ...createMockConfig(), externalBridges },
182
+ multiProvider,
183
+ {
184
+ tokens: [
185
+ createToken(
186
+ 'ethereum',
187
+ TEST_ADDRESSES.ethereum,
188
+ TokenStandard.EvmHypCollateral,
189
+ ),
190
+ createToken(
191
+ 'arbitrum',
192
+ TEST_ADDRESSES.arbitrum,
193
+ TokenStandard.EvmHypCollateral,
194
+ ),
195
+ ],
196
+ },
197
+ );
198
+ }
199
+
200
+ it('returns no bridges when no external bridge is configured', async () => {
201
+ const factory = await factoryWithBridges();
202
+ expect(await factory['buildExternalBridgeRegistry']()).to.deep.equal({});
203
+ });
204
+
205
+ it('awaits the configured LiFi bridge before returning the registry', async () => {
206
+ const factory = await factoryWithBridges({
207
+ lifi: { integrator: 'test-rebalancer' },
208
+ });
209
+ const registry = await factory['buildExternalBridgeRegistry']();
210
+ expect(Object.keys(registry)).to.deep.equal(['lifi']);
211
+ expect(registry.lifi?.externalBridgeId).to.equal('lifi');
212
+ expect(registry.lifi?.getNativeTokenAddress?.()).to.equal(
213
+ '0x0000000000000000000000000000000000000000',
214
+ );
215
+ }).timeout(10_000);
216
+ });
217
+
218
+ describe('createActionTracker() — pending transfer middlewares', () => {
219
+ const BLACKLIST_ISM = '0x5555555555555555555555555555555555555555';
220
+ const mailboxInterface = Mailbox__factory.createInterface();
221
+ const blacklistInterface = BlacklistIsm__factory.createInterface();
222
+
223
+ const DEFAULT_ISM = '0x6666666666666666666666666666666666666666';
224
+
225
+ /**
226
+ * Every router has the BlacklistIsm as its own ISM, which has no
227
+ * blacklisted ids.
228
+ */
229
+ function createIsmProvider(): providers.Provider {
230
+ const provider = new ethers.providers.StaticJsonRpcProvider(
231
+ 'http://127.0.0.1:1',
232
+ { chainId: 1, name: 'fake' },
233
+ );
234
+ Sinon.stub(provider, 'call').callsFake(async (tx) => {
235
+ const { data } = await ethers.utils.resolveProperties(tx);
236
+ if (typeof data !== 'string') throw new Error('Unexpected call');
237
+
238
+ if (data.startsWith(mailboxInterface.getSighash('recipientIsm'))) {
239
+ return mailboxInterface.encodeFunctionResult('recipientIsm', [
240
+ BLACKLIST_ISM,
241
+ ]);
242
+ }
243
+ if (data.startsWith(mailboxInterface.getSighash('defaultIsm'))) {
244
+ return mailboxInterface.encodeFunctionResult('defaultIsm', [
245
+ DEFAULT_ISM,
246
+ ]);
247
+ }
248
+ if (data.startsWith(blacklistInterface.getSighash('values'))) {
249
+ return blacklistInterface.encodeFunctionResult('values', [[]]);
250
+ }
251
+ throw new Error(`Unexpected call ${data}`);
252
+ });
253
+
254
+ return provider;
255
+ }
256
+
257
+ const DOMAINS: Record<string, number> = { ethereum: 1, arbitrum: 42161 };
258
+ const explorer: IExplorerClient = {
259
+ getInflightUserTransfers: async () => [],
260
+ getInflightRebalanceActions: async () => [],
261
+ };
262
+
263
+ let deriveIsmConfig: Sinon.SinonStub;
264
+
265
+ async function createTracker(
266
+ pendingTransferMiddlewares?: PendingTransferMiddlewareConfig[],
267
+ ): Promise<ActionTracker> {
268
+ const { multiProvider } = createMockMultiProvider([
269
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
270
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
271
+ ]);
272
+ multiProvider.getDomainId.callsFake((chain) => {
273
+ const domain = DOMAINS[String(chain)];
274
+ assert(domain, `No domain in mock for chain ${chain}`);
275
+
276
+ return domain;
277
+ });
278
+ multiProvider.getSigner.returns(
279
+ new ethers.VoidSigner(TEST_ADDRESSES.signer),
280
+ );
281
+ multiProvider.getProtocol.returns(ProtocolType.Ethereum);
282
+ multiProvider.getProvider.returns(createIsmProvider());
283
+ multiProvider.getChainName.callsFake((domain) => {
284
+ const chain = Object.keys(DOMAINS).find(
285
+ (name) => DOMAINS[name] === domain,
286
+ );
287
+ assert(chain, `No chain in mock for domain ${domain}`);
288
+
289
+ return chain;
290
+ });
291
+ multiProvider.getChainMetadata.callsFake((chain) => ({
292
+ name: String(chain),
293
+ chainId: DOMAINS[String(chain)],
294
+ domainId: DOMAINS[String(chain)],
295
+ protocol: ProtocolType.Ethereum,
296
+ rpcUrls: [{ http: 'http://127.0.0.1:1' }],
297
+ }));
298
+ multiProvider.tryGetEvmExplorerMetadataList.returns([]);
299
+ deriveIsmConfig = sandbox
300
+ .stub(EvmIsmReader.prototype, 'deriveIsmConfigFromAddress')
301
+ .resolves({
302
+ type: IsmType.BLACKLIST,
303
+ address: BLACKLIST_ISM,
304
+ owner: TEST_ADDRESSES.signer,
305
+ blacklistedIds: [],
306
+ });
307
+
308
+ sandbox
309
+ .stub(MultiProtocolCore, 'fromAddressesMap')
310
+ .returns(Sinon.createStubInstance(MultiProtocolCore));
311
+
312
+ const base = createMockConfig();
313
+ const factory = await createFactory(
314
+ new RebalancerConfig(
315
+ base.warpRouteId,
316
+ base.strategyConfig,
317
+ base.intentTTL,
318
+ undefined,
319
+ undefined,
320
+ pendingTransferMiddlewares,
321
+ ),
322
+ multiProvider,
323
+ {
324
+ tokens: [
325
+ createToken(
326
+ 'ethereum',
327
+ TEST_ADDRESSES.ethereum,
328
+ TokenStandard.EvmHypCollateral,
329
+ ),
330
+ createToken(
331
+ 'arbitrum',
332
+ TEST_ADDRESSES.arbitrum,
333
+ TokenStandard.EvmHypCollateral,
334
+ ),
335
+ ],
336
+ },
337
+ );
338
+
339
+ const { tracker } = await factory.createActionTracker(explorer);
340
+ assert(tracker instanceof ActionTracker, 'Expected an ActionTracker');
341
+
342
+ return tracker;
343
+ }
344
+
345
+ it('uses the Explorer client unchanged when no middlewares are configured', async () => {
346
+ const tracker = await createTracker();
347
+
348
+ expect(tracker['explorerClient']).to.equal(explorer);
349
+ expect(tracker['config'].isIgnoredTransfer).to.equal(undefined);
350
+ expect(tracker['config'].isIgnoredRebalanceAction).to.equal(undefined);
351
+ });
352
+
353
+ it('wraps the Explorer client and passes the predicate when middlewares are configured', async () => {
354
+ const tracker = await createTracker([
355
+ {
356
+ type: PendingTransferMiddlewareType.BlacklistIsm,
357
+ refreshIntervalSecs: 600,
358
+ },
359
+ ]);
360
+
361
+ const client = tracker['explorerClient'];
362
+ assert(
363
+ client instanceof BlacklistIsmMiddleware,
364
+ 'Expected a BlacklistIsmMiddleware',
365
+ );
366
+
367
+ expect(client['inner']).to.equal(explorer);
368
+ expect(tracker['config'].isIgnoredTransfer).to.be.a('function');
369
+ expect(tracker['config'].isIgnoredRebalanceAction).to.be.a('function');
370
+ expect(client['options'].mailboxByDomain).to.deep.equal({
371
+ 1: TEST_ADDRESSES.ethereum,
372
+ 42161: TEST_ADDRESSES.ethereum,
373
+ });
374
+ expect(client['options'].routersByDomain).to.deep.equal({
375
+ 1: TEST_ADDRESSES.ethereum,
376
+ 42161: TEST_ADDRESSES.arbitrum,
377
+ });
378
+ expect(client['options'].refreshIntervalMs).to.equal(600_000);
379
+ expect(
380
+ deriveIsmConfig.getCalls().map((call) => call.args[0]),
381
+ ).to.deep.equal([
382
+ ethers.utils.getAddress(BLACKLIST_ISM),
383
+ ethers.utils.getAddress(BLACKLIST_ISM),
384
+ ]);
385
+ });
386
+ });
387
+
159
388
  describe('create() — non-EVM chain handling', () => {
160
389
  it('should skip provider initialization for StarkNet chains', async () => {
161
390
  const { multiProvider } = createMockMultiProvider([
@@ -218,6 +447,36 @@ describe('RebalancerContextFactory', () => {
218
447
  expect(multiProvider.getProvider.firstCall.args[0]).to.equal('ethereum');
219
448
  });
220
449
 
450
+ it('should initialize providers for Tron chains (EVM-like)', async () => {
451
+ const { multiProvider } = createMockMultiProvider([
452
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
453
+ { name: 'tron', protocol: ProtocolType.Tron },
454
+ ]);
455
+
456
+ await callCreate(multiProvider, {
457
+ tokens: [
458
+ createToken(
459
+ 'ethereum',
460
+ TEST_ADDRESSES.ethereum,
461
+ TokenStandard.EvmHypCollateral,
462
+ ),
463
+ createToken(
464
+ 'tron',
465
+ '0xTronToken1234567890',
466
+ TokenStandard.TronHypCollateral,
467
+ ),
468
+ ],
469
+ });
470
+
471
+ // Tron is EVM-like, so getProvider should be called for both chains
472
+ expect(multiProvider.getProvider.callCount).to.equal(2);
473
+ const providerChains = multiProvider.getProvider
474
+ .getCalls()
475
+ .map((c) => c.args[0]);
476
+ expect(providerChains).to.include('ethereum');
477
+ expect(providerChains).to.include('tron');
478
+ });
479
+
221
480
  it('should call getProvider for all chains when all are EVM', async () => {
222
481
  const { multiProvider } = createMockMultiProvider([
223
482
  { name: 'ethereum', protocol: ProtocolType.Ethereum },
@@ -247,6 +506,78 @@ describe('RebalancerContextFactory', () => {
247
506
  expect(providerChains).to.include('arbitrum');
248
507
  });
249
508
 
509
+ it('should fail fast when bridgeMinAcceptedAmount is configured for a chain without a token', async () => {
510
+ const { multiProvider } = createMockMultiProvider([
511
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
512
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
513
+ ]);
514
+
515
+ const config = createMockConfig();
516
+ config.strategyConfig[0].chains.arbitrum.bridgeMinAcceptedAmount = 1;
517
+
518
+ let error: Error | undefined;
519
+ try {
520
+ const factory = await createFactory(config, multiProvider, {
521
+ tokens: [
522
+ createToken(
523
+ 'ethereum',
524
+ TEST_ADDRESSES.ethereum,
525
+ TokenStandard.EvmHypCollateral,
526
+ ),
527
+ ],
528
+ } as WarpCoreConfig);
529
+ await factory.createStrategy();
530
+ } catch (caught) {
531
+ error = caught as Error;
532
+ }
533
+
534
+ expect(error?.message).to.equal(
535
+ 'No token found for configured strategy chain arbitrum in warp route USDC/paradex',
536
+ );
537
+ });
538
+
539
+ it('should fail fast when bridged supply is unavailable during initial collateral calculation', async () => {
540
+ const { multiProvider } = createMockMultiProvider([
541
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
542
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
543
+ ]);
544
+
545
+ const factory = await createFactory(createMockConfig(), multiProvider, {
546
+ tokens: [
547
+ createToken(
548
+ 'ethereum',
549
+ TEST_ADDRESSES.ethereum,
550
+ TokenStandard.EvmHypCollateral,
551
+ ),
552
+ createToken(
553
+ 'arbitrum',
554
+ TEST_ADDRESSES.arbitrum,
555
+ TokenStandard.EvmHypSynthetic,
556
+ ),
557
+ ],
558
+ });
559
+
560
+ const collateralToken = factory
561
+ .getWarpCore()
562
+ .tokens.find((token) => token.chainName === 'ethereum');
563
+ assert(collateralToken, 'Expected ethereum collateral token in test');
564
+
565
+ sandbox.stub(collateralToken, 'getHypAdapter').returns({
566
+ getBridgedSupply: sandbox.stub().resolves(undefined),
567
+ } as any);
568
+
569
+ let error: Error | undefined;
570
+ try {
571
+ await factory.createStrategy();
572
+ } catch (caught) {
573
+ error = caught as Error;
574
+ }
575
+
576
+ expect(error?.message).to.equal(
577
+ 'Missing bridged supply for ethereum while computing initial total collateral for warp route USDC/paradex',
578
+ );
579
+ });
580
+
250
581
  it('should fail early when inventory override origin protocol signer key is missing', async () => {
251
582
  const sealevelChain = 'solana';
252
583
  const evmChain = 'ethereum';
@@ -291,7 +622,7 @@ describe('RebalancerContextFactory', () => {
291
622
  createToken(
292
623
  evmChain,
293
624
  TEST_ADDRESSES.ethereum,
294
- TokenStandard.EvmHypSynthetic,
625
+ TokenStandard.EvmHypCollateral,
295
626
  ),
296
627
  createToken(
297
628
  sealevelChain,
@@ -310,13 +641,155 @@ describe('RebalancerContextFactory', () => {
310
641
  : ProtocolType.Ethereum,
311
642
  }));
312
643
 
313
- await expect(
314
- (factory as any).createInventoryRebalancerAndConfig({} as any, {}),
315
- ).to.be.rejectedWith(
644
+ let error: Error | undefined;
645
+ try {
646
+ await (factory as any).createInventoryRebalancerAndConfig(
647
+ {} as any,
648
+ {},
649
+ );
650
+ } catch (caught) {
651
+ error = caught as Error;
652
+ }
653
+
654
+ expect(error?.message).to.contain(
316
655
  `Missing inventory signer key for protocol ${ProtocolType.Sealevel}`,
317
656
  );
318
657
  });
319
658
 
659
+ it('should fail early when an inventory-relevant chain has no token', async () => {
660
+ const { multiProvider } = createMockMultiProvider([
661
+ { name: 'ethereum', protocol: ProtocolType.Ethereum },
662
+ { name: 'arbitrum', protocol: ProtocolType.Ethereum },
663
+ ]);
664
+
665
+ const config = {
666
+ ...createMockConfig(),
667
+ inventorySigners: {
668
+ [ProtocolType.Ethereum]: {
669
+ address: TEST_ADDRESSES.ethereum,
670
+ key: '0xabc123',
671
+ },
672
+ },
673
+ } as RebalancerConfig;
674
+ config.strategyConfig[0].chains.arbitrum.executionType =
675
+ ExecutionType.Inventory;
676
+
677
+ const factory = await createFactory(config, multiProvider, {
678
+ tokens: [
679
+ createToken(
680
+ 'ethereum',
681
+ TEST_ADDRESSES.ethereum,
682
+ TokenStandard.EvmHypCollateral,
683
+ ),
684
+ ],
685
+ });
686
+
687
+ const getChainMetadataStub = factory.getWarpCore().multiProvider
688
+ .getChainMetadata as Sinon.SinonStub;
689
+ getChainMetadataStub.callsFake(() => ({
690
+ protocol: ProtocolType.Ethereum,
691
+ }));
692
+
693
+ let error: Error | undefined;
694
+ try {
695
+ await (factory as any).createInventoryRebalancerAndConfig(
696
+ {} as any,
697
+ {},
698
+ );
699
+ } catch (caught) {
700
+ error = caught as Error;
701
+ }
702
+
703
+ expect(error?.message).to.equal(
704
+ 'No token found for inventory-relevant chain arbitrum in warp route USDC/paradex',
705
+ );
706
+ });
707
+
708
+ it('should accept Tron as a supported inventory protocol', async () => {
709
+ const tronChain = 'tron';
710
+ const evmChain = 'ethereum';
711
+ const { multiProvider } = createMockMultiProvider([
712
+ { name: evmChain, protocol: ProtocolType.Ethereum },
713
+ { name: tronChain, protocol: ProtocolType.Tron },
714
+ ]);
715
+
716
+ const config = {
717
+ warpRouteId: 'USDC/tron-route',
718
+ strategyConfig: [
719
+ {
720
+ rebalanceStrategy: RebalancerStrategyOptions.Weighted,
721
+ chains: {
722
+ [tronChain]: {
723
+ bridge: TEST_ADDRESSES.bridge,
724
+ weighted: { weight: 50n, tolerance: 10n },
725
+ override: {
726
+ [evmChain]: {
727
+ executionType: ExecutionType.Inventory,
728
+ },
729
+ },
730
+ },
731
+ [evmChain]: {
732
+ bridge: TEST_ADDRESSES.bridge,
733
+ weighted: { weight: 50n, tolerance: 10n },
734
+ },
735
+ },
736
+ },
737
+ ],
738
+ inventorySigners: {
739
+ [ProtocolType.Ethereum]: {
740
+ address: TEST_ADDRESSES.ethereum,
741
+ key: '0xabc123',
742
+ },
743
+ [ProtocolType.Tron]: {
744
+ address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
745
+ key: '0xdef456',
746
+ },
747
+ },
748
+ intentTTL: DEFAULT_INTENT_TTL_MS,
749
+ } as RebalancerConfig;
750
+
751
+ const factory = await createFactory(config, multiProvider, {
752
+ tokens: [
753
+ createToken(
754
+ evmChain,
755
+ TEST_ADDRESSES.ethereum,
756
+ TokenStandard.EvmHypCollateral,
757
+ ),
758
+ createToken(
759
+ tronChain,
760
+ '0xTronToken123',
761
+ TokenStandard.TronHypCollateral,
762
+ ),
763
+ ],
764
+ });
765
+
766
+ const getChainMetadataStub = factory.getWarpCore().multiProvider
767
+ .getChainMetadata as Sinon.SinonStub;
768
+ getChainMetadataStub.callsFake((chainName: string) => ({
769
+ protocol:
770
+ chainName === tronChain ? ProtocolType.Tron : ProtocolType.Ethereum,
771
+ }));
772
+
773
+ const result = await (factory as any).createInventoryRebalancerAndConfig(
774
+ {} as any,
775
+ {},
776
+ );
777
+
778
+ assert(
779
+ result,
780
+ 'Expected inventory config to be created for Tron support',
781
+ );
782
+ expect(result.inventoryConfig.inventoryAddresses).to.deep.equal({
783
+ [ProtocolType.Ethereum]: TEST_ADDRESSES.ethereum,
784
+ [ProtocolType.Tron]: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
785
+ });
786
+ expect(result.inventoryConfig.chains).to.include.members([
787
+ evmChain,
788
+ tronChain,
789
+ ]);
790
+ expect(result.inventoryRebalancer).to.exist;
791
+ });
792
+
320
793
  it('should fail early when inventory chain uses unsupported protocol', async () => {
321
794
  const cosmosChain = 'cosmoshub';
322
795
  const evmChain = 'ethereum';
@@ -384,9 +857,17 @@ describe('RebalancerContextFactory', () => {
384
857
  : ProtocolType.Ethereum,
385
858
  }));
386
859
 
387
- await expect(
388
- (factory as any).createInventoryRebalancerAndConfig({} as any, {}),
389
- ).to.be.rejectedWith(
860
+ let error: Error | undefined;
861
+ try {
862
+ await (factory as any).createInventoryRebalancerAndConfig(
863
+ {} as any,
864
+ {},
865
+ );
866
+ } catch (caught) {
867
+ error = caught as Error;
868
+ }
869
+
870
+ expect(error?.message).to.contain(
390
871
  `Inventory rebalancing does not support protocol '${ProtocolType.Cosmos}'`,
391
872
  );
392
873
  });