@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
@@ -14,12 +14,11 @@ import {
14
14
  import {
15
15
  Address,
16
16
  assert,
17
+ isEVMLike,
17
18
  ProtocolType,
18
19
  objMap,
19
- toWei,
20
20
  } from '@humanode-hyperlane/utils';
21
21
 
22
- import { LiFiBridge } from '../bridges/LiFiBridge.js';
23
22
  import { type RebalancerConfig } from '../config/RebalancerConfig.js';
24
23
  import {
25
24
  ExecutionType,
@@ -50,6 +49,7 @@ import {
50
49
  } from '../tracking/ActionTracker.js';
51
50
  import type { IActionTracker } from '../tracking/IActionTracker.js';
52
51
  import { InflightContextAdapter } from '../tracking/InflightContextAdapter.js';
52
+ import { buildPendingTransferMiddlewares } from '../tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js';
53
53
  import { InMemoryStore } from '../tracking/store/index.js';
54
54
  import type {
55
55
  RebalanceAction,
@@ -63,6 +63,10 @@ import {
63
63
  ExplorerClient,
64
64
  type IExplorerClient,
65
65
  } from '../utils/ExplorerClient.js';
66
+ import {
67
+ normalizeConfiguredAmount,
68
+ normalizeToCanonical,
69
+ } from '../utils/balanceUtils.js';
66
70
  import { isCollateralizedTokenEligibleForRebalancing } from '../utils/tokenUtils.js';
67
71
 
68
72
  const DEFAULT_EXPLORER_URL =
@@ -139,7 +143,7 @@ export class RebalancerContextFactory {
139
143
  ...new Set(warpCoreConfig.tokens.map((t) => t.chainName)),
140
144
  ];
141
145
  for (const chain of warpChains) {
142
- if (multiProvider.getProtocol(chain) !== ProtocolType.Ethereum) {
146
+ if (!isEVMLike(multiProvider.getProtocol(chain))) {
143
147
  logger.debug({ chain }, 'Skipping provider init for non-EVM chain');
144
148
  continue;
145
149
  }
@@ -252,9 +256,13 @@ export class RebalancerContextFactory {
252
256
  );
253
257
  if (chainConfig?.bridgeMinAcceptedAmount) {
254
258
  const token = this.tokensByChainName[chainName];
255
- const decimals = token?.decimals ?? 18;
256
- minAmountsByChain[chainName] = BigInt(
257
- toWei(chainConfig.bridgeMinAcceptedAmount, decimals),
259
+ assert(
260
+ token,
261
+ `No token found for configured strategy chain ${chainName} in warp route ${this.config.warpRouteId}`,
262
+ );
263
+ minAmountsByChain[chainName] = normalizeConfiguredAmount(
264
+ chainConfig.bridgeMinAcceptedAmount,
265
+ token,
258
266
  );
259
267
  }
260
268
  }
@@ -321,7 +329,7 @@ export class RebalancerContextFactory {
321
329
  RebalanceActionStatus
322
330
  >();
323
331
 
324
- const explorerClient =
332
+ const baseExplorerClient =
325
333
  typeof explorerUrlOrClient === 'string'
326
334
  ? new ExplorerClient(explorerUrlOrClient, (domain) =>
327
335
  this.multiProvider.getProtocol(domain),
@@ -366,16 +374,40 @@ export class RebalancerContextFactory {
366
374
  routersByDomain[domain] = token.addressOrDenom;
367
375
  }
368
376
 
377
+ const mailboxByDomain: Record<number, string> = {};
378
+ for (const [chain, addresses] of Object.entries(coreAddresses)) {
379
+ mailboxByDomain[this.multiProvider.getDomainId(chain)] =
380
+ addresses.mailbox;
381
+ }
382
+
383
+ const {
384
+ client: explorerClient,
385
+ isIgnoredTransfer,
386
+ isIgnoredRebalanceAction,
387
+ } = await buildPendingTransferMiddlewares(
388
+ baseExplorerClient,
389
+ this.config.pendingTransferMiddlewares ?? [],
390
+ {
391
+ routersByDomain,
392
+ mailboxByDomain,
393
+ multiProvider: this.multiProvider,
394
+ logger: this.logger,
395
+ },
396
+ );
397
+
369
398
  const trackerConfig: ActionTrackerConfig = {
370
399
  routersByDomain,
400
+ isIgnoredTransfer,
401
+ isIgnoredRebalanceAction,
371
402
  bridges,
372
403
  rebalancerAddress,
373
404
  inventorySignerAddresses: this.config.inventorySigners
374
- ? (Object.entries(this.config.inventorySigners)
375
- .filter(([protocol]) => protocol === ProtocolType.Ethereum)
376
- .map(([, signerConfig]) => signerConfig)
377
- .map((s) => s.address)
378
- .filter(Boolean) as Address[])
405
+ ? Object.values(ProtocolType)
406
+ .filter((protocol) => isEVMLike(protocol))
407
+ .map(
408
+ (protocol) => this.config.inventorySigners?.[protocol]?.address,
409
+ )
410
+ .filter((address): address is Address => Boolean(address))
379
411
  : undefined,
380
412
  intentTTL: this.config.intentTTL,
381
413
  };
@@ -459,6 +491,13 @@ export class RebalancerContextFactory {
459
491
  return null;
460
492
  }
461
493
 
494
+ for (const chain of allRelevantChains) {
495
+ assert(
496
+ this.tokensByChainName[chain],
497
+ `No token found for inventory-relevant chain ${chain} in warp route ${this.config.warpRouteId}`,
498
+ );
499
+ }
500
+
462
501
  const requiredProtocols = new Set(
463
502
  allRelevantChains.map((chain) => {
464
503
  const metadata = this.warpCore.multiProvider.getChainMetadata(chain);
@@ -472,6 +511,7 @@ export class RebalancerContextFactory {
472
511
  const SUPPORTED_INVENTORY_PROTOCOLS = new Set([
473
512
  ProtocolType.Ethereum,
474
513
  ProtocolType.Sealevel,
514
+ ProtocolType.Tron,
475
515
  ]);
476
516
  for (const protocol of requiredProtocols) {
477
517
  const chainsForProtocol = allRelevantChains.filter(
@@ -481,7 +521,7 @@ export class RebalancerContextFactory {
481
521
  );
482
522
  assert(
483
523
  SUPPORTED_INVENTORY_PROTOCOLS.has(protocol),
484
- `Inventory rebalancing does not support protocol '${protocol}' (chains: ${chainsForProtocol.join(', ')}). Supported: ethereum, sealevel`,
524
+ `Inventory rebalancing does not support protocol '${protocol}' (chains: ${chainsForProtocol.join(', ')}). Supported: ethereum, sealevel, tron`,
485
525
  );
486
526
  }
487
527
  for (const protocol of requiredProtocols) {
@@ -511,7 +551,8 @@ export class RebalancerContextFactory {
511
551
  }
512
552
 
513
553
  const externalBridgeRegistry: Partial<ExternalBridgeRegistry> =
514
- externalBridgeRegistryOverride ?? this.buildExternalBridgeRegistry();
554
+ externalBridgeRegistryOverride ??
555
+ (await this.buildExternalBridgeRegistry());
515
556
 
516
557
  if (Object.keys(externalBridgeRegistry).length === 0) {
517
558
  if (externalBridgeRegistryOverride !== undefined) {
@@ -523,12 +564,12 @@ export class RebalancerContextFactory {
523
564
  'No external bridges configured, skipping inventory components',
524
565
  );
525
566
  }
526
- const inventoryAddresses = Object.fromEntries(
527
- Object.entries(inventorySigners).map(([protocol, cfg]) => [
528
- protocol,
529
- cfg.address,
530
- ]),
531
- ) as Partial<Record<ProtocolType, Address>>;
567
+ const inventoryAddresses: Partial<Record<ProtocolType, Address>> = {};
568
+ for (const protocol of Object.values(ProtocolType)) {
569
+ const cfg = inventorySigners[protocol];
570
+ if (!cfg) continue;
571
+ inventoryAddresses[protocol] = cfg.address;
572
+ }
532
573
  const inventoryConfig: InventoryMonitorConfig = {
533
574
  inventoryAddresses,
534
575
  chains: allRelevantChains,
@@ -537,11 +578,12 @@ export class RebalancerContextFactory {
537
578
  const mergedSigners: Partial<
538
579
  Record<ProtocolType, InventorySignerConfig>
539
580
  > = {};
540
- for (const [protocol, cfg] of Object.entries(inventorySigners)) {
541
- const protocolKey = protocol as ProtocolType;
542
- mergedSigners[protocolKey] = {
581
+ for (const protocol of Object.values(ProtocolType)) {
582
+ const cfg = inventorySigners[protocol];
583
+ if (!cfg) continue;
584
+ mergedSigners[protocol] = {
543
585
  address: cfg.address,
544
- key: cfg.key ?? this.inventorySignerKeysByProtocol?.[protocolKey],
586
+ key: cfg.key ?? this.inventorySignerKeysByProtocol?.[protocol],
545
587
  };
546
588
  }
547
589
  const inventoryRebalancer = new InventoryRebalancer(
@@ -563,12 +605,12 @@ export class RebalancerContextFactory {
563
605
  }
564
606
 
565
607
  // 3. Build inventory config
566
- const inventoryAddresses = Object.fromEntries(
567
- Object.entries(inventorySigners).map(([protocol, cfg]) => [
568
- protocol,
569
- cfg.address,
570
- ]),
571
- ) as Partial<Record<ProtocolType, Address>>;
608
+ const inventoryAddresses: Partial<Record<ProtocolType, Address>> = {};
609
+ for (const protocol of Object.values(ProtocolType)) {
610
+ const cfg = inventorySigners[protocol];
611
+ if (!cfg) continue;
612
+ inventoryAddresses[protocol] = cfg.address;
613
+ }
572
614
  const inventoryConfig: InventoryMonitorConfig = {
573
615
  inventoryAddresses,
574
616
  chains: allRelevantChains,
@@ -578,11 +620,12 @@ export class RebalancerContextFactory {
578
620
  // Merge config addresses with runtime keys
579
621
  const mergedSigners: Partial<Record<ProtocolType, InventorySignerConfig>> =
580
622
  {};
581
- for (const [protocol, cfg] of Object.entries(inventorySigners)) {
582
- const protocolKey = protocol as ProtocolType;
583
- mergedSigners[protocolKey] = {
623
+ for (const protocol of Object.values(ProtocolType)) {
624
+ const cfg = inventorySigners[protocol];
625
+ if (!cfg) continue;
626
+ mergedSigners[protocol] = {
584
627
  address: cfg.address,
585
- key: cfg.key ?? this.inventorySignerKeysByProtocol?.[protocolKey],
628
+ key: cfg.key ?? this.inventorySignerKeysByProtocol?.[protocol],
586
629
  };
587
630
  }
588
631
  const inventoryRebalancer = new InventoryRebalancer(
@@ -608,7 +651,9 @@ export class RebalancerContextFactory {
608
651
  return { inventoryRebalancer, externalBridgeRegistry, inventoryConfig };
609
652
  }
610
653
 
611
- private buildExternalBridgeRegistry(): Partial<ExternalBridgeRegistry> {
654
+ private async buildExternalBridgeRegistry(): Promise<
655
+ Partial<ExternalBridgeRegistry>
656
+ > {
612
657
  const { externalBridges } = this.config;
613
658
  const registry: Partial<ExternalBridgeRegistry> = {};
614
659
 
@@ -617,6 +662,7 @@ export class RebalancerContextFactory {
617
662
  case ExternalBridgeType.LiFi: {
618
663
  const lifiConfig = externalBridges?.lifi;
619
664
  if (lifiConfig?.integrator) {
665
+ const { LiFiBridge } = await import('../bridges/LiFiBridge.js');
620
666
  registry[ExternalBridgeType.LiFi] = new LiFiBridge(
621
667
  {
622
668
  integrator: lifiConfig.integrator,
@@ -761,7 +807,11 @@ export class RebalancerContextFactory {
761
807
  ) {
762
808
  const adapter = token.getHypAdapter(this.warpCore.multiProvider);
763
809
  const bridgedSupply = await adapter.getBridgedSupply();
764
- initialTotalCollateral += bridgedSupply ?? 0n;
810
+ assert(
811
+ bridgedSupply !== undefined,
812
+ `Missing bridged supply for ${token.chainName} while computing initial total collateral for warp route ${this.config.warpRouteId}`,
813
+ );
814
+ initialTotalCollateral += normalizeToCanonical(bridgedSupply, token);
765
815
  }
766
816
  }),
767
817
  );
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ export {
24
24
  DEFAULT_INTENT_TTL_S,
25
25
  getStrategyChainConfig,
26
26
  getStrategyChainNames,
27
+ PendingTransferMiddlewareType,
27
28
  RebalancerBaseChainConfigSchema,
28
29
  RebalancerConfigSchema,
29
30
  RebalancerMinAmountConfigSchema,
@@ -35,6 +36,7 @@ export {
35
36
  } from './config/types.js';
36
37
  export type {
37
38
  MinAmountStrategyConfig,
39
+ PendingTransferMiddlewareConfig,
38
40
  RebalancerConfig as RebalancerConfigType,
39
41
  RebalancerConfigFileInput,
40
42
  RebalancerMinAmountChainConfig,
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  type EvmMovableCollateralAdapter,
3
+ type IToken,
3
4
  type TokenAmount,
4
5
  } from '@humanode-hyperlane/sdk';
5
6
 
@@ -48,10 +49,12 @@ export type IInventoryRebalancer = IRebalancer<
48
49
  InventoryExecutionResult
49
50
  >;
50
51
 
52
+ type PreparedOriginTokenAmount = TokenAmount<IToken>;
53
+
51
54
  export type PreparedTransaction = {
52
55
  populatedTx: Awaited<
53
56
  ReturnType<EvmMovableCollateralAdapter['populateRebalanceTx']>
54
57
  >;
55
58
  route: MovableCollateralRoute & { intentId: string };
56
- originTokenAmount: TokenAmount;
59
+ originTokenAmount: PreparedOriginTokenAmount;
57
60
  };
@@ -274,6 +274,7 @@ export class Metrics implements IMetrics {
274
274
  this.warpCore.multiProvider,
275
275
  token,
276
276
  lockbox.lockbox,
277
+ balance.tokenAddress,
277
278
  );
278
279
 
279
280
  updateManagedLockboxBalanceMetrics(
@@ -0,0 +1,113 @@
1
+ import { expect } from 'chai';
2
+ import { pino } from 'pino';
3
+ import Sinon from 'sinon';
4
+
5
+ import { CoinGeckoTokenPriceGetter } from '@humanode-hyperlane/sdk';
6
+
7
+ import { PriceGetter } from './PriceGetter.js';
8
+
9
+ const logger = pino({ level: 'silent' });
10
+ const response = (price = 1) =>
11
+ new Response(
12
+ JSON.stringify({
13
+ 'usd-coin': { usd: price },
14
+ tether: { usd: price },
15
+ }),
16
+ );
17
+
18
+ describe('PriceGetter concurrent lookups', () => {
19
+ afterEach(() => Sinon.restore());
20
+
21
+ it('reduces twelve concurrent same-ID HTTP requests to one', async () => {
22
+ const fetch = Sinon.stub(globalThis, 'fetch').callsFake(async () =>
23
+ response(),
24
+ );
25
+ const baseline = new CoinGeckoTokenPriceGetter({
26
+ chainMetadata: {},
27
+ sleepMsBetweenRequests: 0,
28
+ });
29
+ const before = await Promise.all(
30
+ Array.from({ length: 12 }, () =>
31
+ baseline.getTokenPriceByIds(['usd-coin']),
32
+ ),
33
+ );
34
+ expect(fetch.callCount).to.equal(12);
35
+ fetch.resetHistory();
36
+
37
+ const getter = PriceGetter.create({}, logger, undefined, undefined, 0);
38
+ const after = await Promise.all(
39
+ Array.from({ length: 12 }, () => getter.getCoingeckoPrice('usd-coin')),
40
+ );
41
+ expect(fetch.callCount).to.equal(1);
42
+ expect(after).to.deep.equal(before.map((prices) => prices?.[0]));
43
+ });
44
+
45
+ it('looks up distinct IDs independently', async () => {
46
+ const fetch = Sinon.stub(globalThis, 'fetch').callsFake(async () =>
47
+ response(),
48
+ );
49
+ const getter = PriceGetter.create({}, logger, undefined, undefined, 0);
50
+ expect(
51
+ await Promise.all([
52
+ getter.getCoingeckoPrice('usd-coin'),
53
+ getter.getCoingeckoPrice('tether'),
54
+ getter.getCoingeckoPrice('usd-coin'),
55
+ getter.getCoingeckoPrice('tether'),
56
+ ]),
57
+ ).to.deep.equal([1, 1, 1, 1]);
58
+ expect(fetch.callCount).to.equal(2);
59
+ });
60
+
61
+ it('keeps the SDK cache behavior after a successful lookup', async () => {
62
+ const fetch = Sinon.stub(globalThis, 'fetch').callsFake(async () =>
63
+ response(),
64
+ );
65
+ const getter = PriceGetter.create({}, logger, undefined, 60, 0);
66
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(1);
67
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(1);
68
+ expect(fetch.callCount).to.equal(1);
69
+ });
70
+
71
+ it('does not retain settled results beyond the SDK cache lifetime', async () => {
72
+ const fetch = Sinon.stub(globalThis, 'fetch');
73
+ fetch.onFirstCall().resolves(response(1));
74
+ fetch.onSecondCall().resolves(response(2));
75
+ const getter = PriceGetter.create({}, logger, undefined, 0, 0);
76
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(1);
77
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(2);
78
+ expect(fetch.callCount).to.equal(2);
79
+ });
80
+
81
+ it('retries after an unavailable price instead of retaining undefined', async () => {
82
+ const fetch = Sinon.stub(globalThis, 'fetch');
83
+ fetch.onFirstCall().resolves(new Response('{}'));
84
+ fetch.onSecondCall().resolves(response());
85
+ const getter = PriceGetter.create({}, logger, undefined, undefined, 0);
86
+ expect(
87
+ await Promise.all([
88
+ getter.getCoingeckoPrice('usd-coin'),
89
+ getter.getCoingeckoPrice('usd-coin'),
90
+ ]),
91
+ ).to.deep.equal([undefined, undefined]);
92
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(1);
93
+ expect(fetch.callCount).to.equal(2);
94
+ });
95
+
96
+ it('propagates rejected lookups to all callers and allows a retry', async () => {
97
+ const getter = PriceGetter.create({}, logger);
98
+ const lookup = Sinon.stub(getter, 'getTokenPriceByIds');
99
+ const error = new Error('price lookup rejected');
100
+ lookup.onFirstCall().rejects(error);
101
+ lookup.onSecondCall().resolves([2]);
102
+ const results = await Promise.allSettled([
103
+ getter.getCoingeckoPrice('usd-coin'),
104
+ getter.getCoingeckoPrice('usd-coin'),
105
+ ]);
106
+ expect(results).to.deep.equal([
107
+ { status: 'rejected', reason: error },
108
+ { status: 'rejected', reason: error },
109
+ ]);
110
+ expect(await getter.getCoingeckoPrice('usd-coin')).to.equal(2);
111
+ expect(lookup.callCount).to.equal(2);
112
+ });
113
+ });
@@ -9,6 +9,10 @@ import {
9
9
 
10
10
  export class PriceGetter extends CoinGeckoTokenPriceGetter {
11
11
  private readonly logger: Logger;
12
+ private readonly pendingPrices = new Map<
13
+ string,
14
+ Promise<number | undefined>
15
+ >();
12
16
 
13
17
  private constructor({
14
18
  chainMetadata,
@@ -67,8 +71,19 @@ export class PriceGetter extends CoinGeckoTokenPriceGetter {
67
71
  }
68
72
 
69
73
  async getCoingeckoPrice(coingeckoId: string): Promise<number | undefined> {
70
- const prices = await this.getTokenPriceByIds([coingeckoId]);
71
- if (!prices) return undefined;
72
- return prices[0];
74
+ const pending = this.pendingPrices.get(coingeckoId);
75
+ if (pending) return pending;
76
+
77
+ // Multiple route tokens can share an ID. Share only the active lookup;
78
+ // the SDK remains responsible for cache freshness and failed-price handling.
79
+ const request = this.getTokenPriceByIds([coingeckoId]).then(
80
+ (prices) => prices?.[0],
81
+ );
82
+ this.pendingPrices.set(coingeckoId, request);
83
+ try {
84
+ return await request;
85
+ } finally {
86
+ this.pendingPrices.delete(coingeckoId);
87
+ }
73
88
  }
74
89
  }