@hyperlane-xyz/rebalancer 0.1.0-beta.5a8bd28ab

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 (202) hide show
  1. package/README.md +178 -0
  2. package/dist/config/RebalancerConfig.d.ts +12 -0
  3. package/dist/config/RebalancerConfig.d.ts.map +1 -0
  4. package/dist/config/RebalancerConfig.js +29 -0
  5. package/dist/config/RebalancerConfig.js.map +1 -0
  6. package/dist/config/RebalancerConfig.test.d.ts +2 -0
  7. package/dist/config/RebalancerConfig.test.d.ts.map +1 -0
  8. package/dist/config/RebalancerConfig.test.js +325 -0
  9. package/dist/config/RebalancerConfig.test.js.map +1 -0
  10. package/dist/core/Rebalancer.d.ts +23 -0
  11. package/dist/core/Rebalancer.d.ts.map +1 -0
  12. package/dist/core/Rebalancer.js +290 -0
  13. package/dist/core/Rebalancer.js.map +1 -0
  14. package/dist/core/RebalancerService.d.ts +115 -0
  15. package/dist/core/RebalancerService.d.ts.map +1 -0
  16. package/dist/core/RebalancerService.js +227 -0
  17. package/dist/core/RebalancerService.js.map +1 -0
  18. package/dist/core/WithInflightGuard.d.ts +20 -0
  19. package/dist/core/WithInflightGuard.d.ts.map +1 -0
  20. package/dist/core/WithInflightGuard.js +47 -0
  21. package/dist/core/WithInflightGuard.js.map +1 -0
  22. package/dist/core/WithInflightGuard.test.d.ts +2 -0
  23. package/dist/core/WithInflightGuard.test.d.ts.map +1 -0
  24. package/dist/core/WithInflightGuard.test.js +64 -0
  25. package/dist/core/WithInflightGuard.test.js.map +1 -0
  26. package/dist/core/WithSemaphore.d.ts +22 -0
  27. package/dist/core/WithSemaphore.d.ts.map +1 -0
  28. package/dist/core/WithSemaphore.js +67 -0
  29. package/dist/core/WithSemaphore.js.map +1 -0
  30. package/dist/core/WithSemaphore.test.d.ts +2 -0
  31. package/dist/core/WithSemaphore.test.d.ts.map +1 -0
  32. package/dist/core/WithSemaphore.test.js +83 -0
  33. package/dist/core/WithSemaphore.test.js.map +1 -0
  34. package/dist/factories/RebalancerContextFactory.d.ts +41 -0
  35. package/dist/factories/RebalancerContextFactory.d.ts.map +1 -0
  36. package/dist/factories/RebalancerContextFactory.js +115 -0
  37. package/dist/factories/RebalancerContextFactory.js.map +1 -0
  38. package/dist/index.d.ts +33 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +35 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/interfaces/IMetrics.d.ts +5 -0
  43. package/dist/interfaces/IMetrics.d.ts.map +1 -0
  44. package/dist/interfaces/IMetrics.js +2 -0
  45. package/dist/interfaces/IMetrics.js.map +1 -0
  46. package/dist/interfaces/IMonitor.d.ts +51 -0
  47. package/dist/interfaces/IMonitor.d.ts.map +1 -0
  48. package/dist/interfaces/IMonitor.js +14 -0
  49. package/dist/interfaces/IMonitor.js.map +1 -0
  50. package/dist/interfaces/IRebalancer.d.ts +15 -0
  51. package/dist/interfaces/IRebalancer.d.ts.map +1 -0
  52. package/dist/interfaces/IRebalancer.js +2 -0
  53. package/dist/interfaces/IRebalancer.js.map +1 -0
  54. package/dist/interfaces/IStrategy.d.ts +11 -0
  55. package/dist/interfaces/IStrategy.d.ts.map +1 -0
  56. package/dist/interfaces/IStrategy.js +2 -0
  57. package/dist/interfaces/IStrategy.js.map +1 -0
  58. package/dist/metrics/Metrics.d.ts +31 -0
  59. package/dist/metrics/Metrics.d.ts.map +1 -0
  60. package/dist/metrics/Metrics.js +302 -0
  61. package/dist/metrics/Metrics.js.map +1 -0
  62. package/dist/metrics/PriceGetter.d.ts +10 -0
  63. package/dist/metrics/PriceGetter.d.ts.map +1 -0
  64. package/dist/metrics/PriceGetter.js +41 -0
  65. package/dist/metrics/PriceGetter.js.map +1 -0
  66. package/dist/metrics/scripts/metrics.d.ts +14 -0
  67. package/dist/metrics/scripts/metrics.d.ts.map +1 -0
  68. package/dist/metrics/scripts/metrics.js +198 -0
  69. package/dist/metrics/scripts/metrics.js.map +1 -0
  70. package/dist/metrics/types.d.ts +24 -0
  71. package/dist/metrics/types.d.ts.map +1 -0
  72. package/dist/metrics/types.js +2 -0
  73. package/dist/metrics/types.js.map +1 -0
  74. package/dist/metrics/utils/metrics.d.ts +12 -0
  75. package/dist/metrics/utils/metrics.d.ts.map +1 -0
  76. package/dist/metrics/utils/metrics.js +28 -0
  77. package/dist/metrics/utils/metrics.js.map +1 -0
  78. package/dist/monitor/Monitor.d.ts +26 -0
  79. package/dist/monitor/Monitor.d.ts.map +1 -0
  80. package/dist/monitor/Monitor.js +116 -0
  81. package/dist/monitor/Monitor.js.map +1 -0
  82. package/dist/service.d.ts +3 -0
  83. package/dist/service.d.ts.map +1 -0
  84. package/dist/service.js +125 -0
  85. package/dist/service.js.map +1 -0
  86. package/dist/strategy/BaseStrategy.d.ts +34 -0
  87. package/dist/strategy/BaseStrategy.d.ts.map +1 -0
  88. package/dist/strategy/BaseStrategy.js +127 -0
  89. package/dist/strategy/BaseStrategy.js.map +1 -0
  90. package/dist/strategy/MinAmountStrategy.d.ts +27 -0
  91. package/dist/strategy/MinAmountStrategy.d.ts.map +1 -0
  92. package/dist/strategy/MinAmountStrategy.js +103 -0
  93. package/dist/strategy/MinAmountStrategy.js.map +1 -0
  94. package/dist/strategy/MinAmountStrategy.test.d.ts +2 -0
  95. package/dist/strategy/MinAmountStrategy.test.d.ts.map +1 -0
  96. package/dist/strategy/MinAmountStrategy.test.js +472 -0
  97. package/dist/strategy/MinAmountStrategy.test.js.map +1 -0
  98. package/dist/strategy/StrategyFactory.d.ts +16 -0
  99. package/dist/strategy/StrategyFactory.d.ts.map +1 -0
  100. package/dist/strategy/StrategyFactory.js +25 -0
  101. package/dist/strategy/StrategyFactory.js.map +1 -0
  102. package/dist/strategy/StrategyFactory.test.d.ts +2 -0
  103. package/dist/strategy/StrategyFactory.test.d.ts.map +1 -0
  104. package/dist/strategy/StrategyFactory.test.js +80 -0
  105. package/dist/strategy/StrategyFactory.test.js.map +1 -0
  106. package/dist/strategy/WeightedStrategy.d.ts +23 -0
  107. package/dist/strategy/WeightedStrategy.d.ts.map +1 -0
  108. package/dist/strategy/WeightedStrategy.js +61 -0
  109. package/dist/strategy/WeightedStrategy.js.map +1 -0
  110. package/dist/strategy/WeightedStrategy.test.d.ts +2 -0
  111. package/dist/strategy/WeightedStrategy.test.d.ts.map +1 -0
  112. package/dist/strategy/WeightedStrategy.test.js +307 -0
  113. package/dist/strategy/WeightedStrategy.test.js.map +1 -0
  114. package/dist/strategy/index.d.ts +5 -0
  115. package/dist/strategy/index.d.ts.map +1 -0
  116. package/dist/strategy/index.js +5 -0
  117. package/dist/strategy/index.js.map +1 -0
  118. package/dist/test/helpers.d.ts +8 -0
  119. package/dist/test/helpers.d.ts.map +1 -0
  120. package/dist/test/helpers.js +33 -0
  121. package/dist/test/helpers.js.map +1 -0
  122. package/dist/utils/ExplorerClient.d.ts +14 -0
  123. package/dist/utils/ExplorerClient.d.ts.map +1 -0
  124. package/dist/utils/ExplorerClient.js +82 -0
  125. package/dist/utils/ExplorerClient.js.map +1 -0
  126. package/dist/utils/balanceUtils.d.ts +13 -0
  127. package/dist/utils/balanceUtils.d.ts.map +1 -0
  128. package/dist/utils/balanceUtils.js +43 -0
  129. package/dist/utils/balanceUtils.js.map +1 -0
  130. package/dist/utils/balanceUtils.test.d.ts +2 -0
  131. package/dist/utils/balanceUtils.test.d.ts.map +1 -0
  132. package/dist/utils/balanceUtils.test.js +54 -0
  133. package/dist/utils/balanceUtils.test.js.map +1 -0
  134. package/dist/utils/bridgeUtils.d.ts +19 -0
  135. package/dist/utils/bridgeUtils.d.ts.map +1 -0
  136. package/dist/utils/bridgeUtils.js +20 -0
  137. package/dist/utils/bridgeUtils.js.map +1 -0
  138. package/dist/utils/bridgeUtils.test.d.ts +2 -0
  139. package/dist/utils/bridgeUtils.test.d.ts.map +1 -0
  140. package/dist/utils/bridgeUtils.test.js +77 -0
  141. package/dist/utils/bridgeUtils.test.js.map +1 -0
  142. package/dist/utils/errors.d.ts +4 -0
  143. package/dist/utils/errors.d.ts.map +1 -0
  144. package/dist/utils/errors.js +6 -0
  145. package/dist/utils/errors.js.map +1 -0
  146. package/dist/utils/files.d.ts +35 -0
  147. package/dist/utils/files.d.ts.map +1 -0
  148. package/dist/utils/files.js +190 -0
  149. package/dist/utils/files.js.map +1 -0
  150. package/dist/utils/generalUtils.d.ts +3 -0
  151. package/dist/utils/generalUtils.d.ts.map +1 -0
  152. package/dist/utils/generalUtils.js +9 -0
  153. package/dist/utils/generalUtils.js.map +1 -0
  154. package/dist/utils/index.d.ts +5 -0
  155. package/dist/utils/index.d.ts.map +1 -0
  156. package/dist/utils/index.js +5 -0
  157. package/dist/utils/index.js.map +1 -0
  158. package/dist/utils/tokenUtils.d.ts +14 -0
  159. package/dist/utils/tokenUtils.d.ts.map +1 -0
  160. package/dist/utils/tokenUtils.js +21 -0
  161. package/dist/utils/tokenUtils.js.map +1 -0
  162. package/package.json +70 -0
  163. package/src/config/RebalancerConfig.test.ts +388 -0
  164. package/src/config/RebalancerConfig.ts +39 -0
  165. package/src/core/Rebalancer.ts +471 -0
  166. package/src/core/RebalancerService.ts +333 -0
  167. package/src/core/WithInflightGuard.test.ts +131 -0
  168. package/src/core/WithInflightGuard.ts +67 -0
  169. package/src/core/WithSemaphore.test.ts +112 -0
  170. package/src/core/WithSemaphore.ts +92 -0
  171. package/src/factories/RebalancerContextFactory.ts +210 -0
  172. package/src/index.ts +68 -0
  173. package/src/interfaces/IMetrics.ts +5 -0
  174. package/src/interfaces/IMonitor.ts +63 -0
  175. package/src/interfaces/IRebalancer.ts +20 -0
  176. package/src/interfaces/IStrategy.ts +13 -0
  177. package/src/metrics/Metrics.ts +558 -0
  178. package/src/metrics/PriceGetter.ts +74 -0
  179. package/src/metrics/scripts/metrics.ts +298 -0
  180. package/src/metrics/types.ts +27 -0
  181. package/src/metrics/utils/metrics.ts +33 -0
  182. package/src/monitor/Monitor.ts +174 -0
  183. package/src/service.ts +154 -0
  184. package/src/strategy/BaseStrategy.ts +210 -0
  185. package/src/strategy/MinAmountStrategy.test.ts +625 -0
  186. package/src/strategy/MinAmountStrategy.ts +170 -0
  187. package/src/strategy/StrategyFactory.test.ts +109 -0
  188. package/src/strategy/StrategyFactory.ts +48 -0
  189. package/src/strategy/WeightedStrategy.test.ts +408 -0
  190. package/src/strategy/WeightedStrategy.ts +93 -0
  191. package/src/strategy/index.ts +4 -0
  192. package/src/test/helpers.ts +46 -0
  193. package/src/utils/ExplorerClient.ts +99 -0
  194. package/src/utils/balanceUtils.test.ts +74 -0
  195. package/src/utils/balanceUtils.ts +69 -0
  196. package/src/utils/bridgeUtils.test.ts +92 -0
  197. package/src/utils/bridgeUtils.ts +42 -0
  198. package/src/utils/errors.ts +5 -0
  199. package/src/utils/files.ts +276 -0
  200. package/src/utils/generalUtils.ts +13 -0
  201. package/src/utils/index.ts +4 -0
  202. package/src/utils/tokenUtils.ts +26 -0
@@ -0,0 +1,290 @@
1
+ import { EvmMovableCollateralAdapter, } from '@hyperlane-xyz/sdk';
2
+ import { eqAddress, toWei } from '@hyperlane-xyz/utils';
3
+ import { getBridgeConfig, } from '../utils/index.js';
4
+ export class Rebalancer {
5
+ bridges;
6
+ warpCore;
7
+ chainMetadata;
8
+ tokensByChainName;
9
+ multiProvider;
10
+ metrics;
11
+ logger;
12
+ constructor(bridges, warpCore, chainMetadata, tokensByChainName, multiProvider, logger, metrics) {
13
+ this.bridges = bridges;
14
+ this.warpCore = warpCore;
15
+ this.chainMetadata = chainMetadata;
16
+ this.tokensByChainName = tokensByChainName;
17
+ this.multiProvider = multiProvider;
18
+ this.metrics = metrics;
19
+ this.logger = logger.child({ class: Rebalancer.name });
20
+ }
21
+ async rebalance(routes) {
22
+ if (routes.length === 0) {
23
+ this.logger.info('No routes to execute, exiting');
24
+ return;
25
+ }
26
+ this.logger.info({ numberOfRoutes: routes.length }, 'Rebalance initiated');
27
+ const { preparedTransactions, preparationFailures } = await this.prepareTransactions(routes);
28
+ let gasEstimationFailures = 0;
29
+ let transactionFailures = 0;
30
+ let successfulTransactions = [];
31
+ if (preparedTransactions.length > 0) {
32
+ const filteredTransactions = this.filterTransactions(preparedTransactions);
33
+ if (filteredTransactions.length > 0) {
34
+ ({
35
+ gasEstimationFailures,
36
+ transactionFailures,
37
+ successfulTransactions,
38
+ } = await this.executeTransactions(filteredTransactions));
39
+ }
40
+ }
41
+ if (preparationFailures > 0 ||
42
+ gasEstimationFailures > 0 ||
43
+ transactionFailures > 0) {
44
+ this.logger.error({
45
+ preparationFailures,
46
+ gasEstimationFailures,
47
+ transactionFailures,
48
+ }, 'A rebalance stage failed.');
49
+ throw new Error('❌ Some rebalance transaction failed');
50
+ }
51
+ if (this.metrics && successfulTransactions.length > 0) {
52
+ for (const transaction of successfulTransactions) {
53
+ this.metrics.recordRebalanceAmount(transaction.route, transaction.originTokenAmount);
54
+ }
55
+ }
56
+ this.logger.info('✅ Rebalance successful');
57
+ return;
58
+ }
59
+ async prepareTransactions(routes) {
60
+ this.logger.info({ numRoutes: routes.length }, 'Preparing all rebalance transactions.');
61
+ const settledResults = await Promise.allSettled(routes.map((route) => this.prepareTransaction(route)));
62
+ const preparedTransactions = [];
63
+ for (const result of settledResults) {
64
+ if (result.status === 'fulfilled' && result.value) {
65
+ preparedTransactions.push(result.value);
66
+ }
67
+ }
68
+ const preparationFailures = routes.length - preparedTransactions.length;
69
+ return { preparedTransactions, preparationFailures };
70
+ }
71
+ async prepareTransaction(route) {
72
+ const { origin, destination, amount } = route;
73
+ this.logger.info({
74
+ origin,
75
+ destination,
76
+ amount,
77
+ }, 'Preparing transaction for route');
78
+ // 1. Adapter and permissions validation
79
+ if (!(await this.validateRoute(route))) {
80
+ // Errors logged in validateRoute
81
+ return null;
82
+ }
83
+ const originToken = this.tokensByChainName[origin];
84
+ const destinationToken = this.tokensByChainName[destination];
85
+ const destinationChainMeta = this.chainMetadata[destination];
86
+ const originTokenAmount = originToken.amount(amount);
87
+ const decimalFormattedAmount = originTokenAmount.getDecimalFormattedAmount();
88
+ const originHypAdapter = originToken.getHypAdapter(this.warpCore.multiProvider);
89
+ const { bridge, bridgeIsWarp } = getBridgeConfig(this.bridges, origin, destination, this.logger);
90
+ // 2. Get quotes
91
+ let quotes;
92
+ try {
93
+ quotes = await originHypAdapter.getRebalanceQuotes(bridge, destinationChainMeta.domainId, destinationToken.addressOrDenom, amount, bridgeIsWarp);
94
+ }
95
+ catch (error) {
96
+ this.logger.error({
97
+ origin,
98
+ destination,
99
+ amount: decimalFormattedAmount,
100
+ tokenName: originToken.name,
101
+ error,
102
+ }, 'Failed to get quotes for route.');
103
+ return null;
104
+ }
105
+ // 3. Populate transaction
106
+ let populatedTx;
107
+ try {
108
+ populatedTx = await originHypAdapter.populateRebalanceTx(destinationChainMeta.domainId, amount, bridge, quotes);
109
+ }
110
+ catch (error) {
111
+ this.logger.error({
112
+ origin,
113
+ destination,
114
+ amount: decimalFormattedAmount,
115
+ tokenName: originToken.name,
116
+ error,
117
+ }, 'Failed to populate transaction for route.');
118
+ return null;
119
+ }
120
+ return { populatedTx, route, originTokenAmount };
121
+ }
122
+ async validateRoute(route) {
123
+ const { origin, destination, amount } = route;
124
+ const originToken = this.tokensByChainName[origin];
125
+ const destinationToken = this.tokensByChainName[destination];
126
+ const destinationDomain = this.chainMetadata[destination];
127
+ if (!originToken) {
128
+ this.logger.error({ origin, destination, amount }, 'Route validation failed: origin token not found.');
129
+ return false;
130
+ }
131
+ const originTokenAmount = originToken.amount(amount);
132
+ const decimalFormattedAmount = originTokenAmount.getDecimalFormattedAmount();
133
+ if (!destinationToken) {
134
+ this.logger.error({ origin, destination, amount: decimalFormattedAmount }, 'Route validation failed: destination token not found.');
135
+ return false;
136
+ }
137
+ if (!destinationDomain) {
138
+ this.logger.error({ origin, destination, amount: decimalFormattedAmount }, 'Route validation failed: destination domain metadata not found.');
139
+ return false;
140
+ }
141
+ const originHypAdapter = originToken.getHypAdapter(this.warpCore.multiProvider);
142
+ if (!(originHypAdapter instanceof EvmMovableCollateralAdapter)) {
143
+ this.logger.error({
144
+ origin,
145
+ destination,
146
+ amount: decimalFormattedAmount,
147
+ tokenName: originToken.name,
148
+ }, 'Route validation failed: Origin TokenAdapter is not an EvmHypCollateralAdapter.');
149
+ return false;
150
+ }
151
+ const signer = this.multiProvider.getSigner(origin);
152
+ const signerAddress = await signer.getAddress();
153
+ if (!(await originHypAdapter.isRebalancer(signerAddress))) {
154
+ this.logger.error({
155
+ origin,
156
+ destination,
157
+ amount: decimalFormattedAmount,
158
+ tokenName: originToken.name,
159
+ tokenAddress: originToken.addressOrDenom,
160
+ signerAddress,
161
+ }, 'Route validation failed: Signer is not a rebalancer.');
162
+ return false;
163
+ }
164
+ const allowedDestination = await originHypAdapter.getAllowedDestination(destinationDomain.domainId);
165
+ if (!eqAddress(allowedDestination, destinationToken.addressOrDenom)) {
166
+ this.logger.error({
167
+ origin,
168
+ destination,
169
+ amount: decimalFormattedAmount,
170
+ tokenName: originToken.name,
171
+ tokenAddress: originToken.addressOrDenom,
172
+ destinationTokenAddress: destinationToken.addressOrDenom,
173
+ allowedDestinationTokenAddress: allowedDestination,
174
+ }, 'Route validation failed: Destination is not allowed.');
175
+ return false;
176
+ }
177
+ const { bridge } = getBridgeConfig(this.bridges, origin, destination, this.logger);
178
+ if (!(await originHypAdapter.isBridgeAllowed(destinationDomain.domainId, bridge))) {
179
+ this.logger.error({
180
+ origin,
181
+ destination,
182
+ amount: decimalFormattedAmount,
183
+ tokenName: originToken.name,
184
+ tokenAddress: originToken.addressOrDenom,
185
+ bridgeAddress: bridge,
186
+ }, 'Route validation failed: Bridge is not allowed.');
187
+ return false;
188
+ }
189
+ return true;
190
+ }
191
+ async executeTransactions(transactions) {
192
+ this.logger.info({ numTransactions: transactions.length }, 'Estimating gas for all prepared transactions.');
193
+ // 1. Estimate gas
194
+ const gasEstimateResults = await Promise.allSettled(transactions.map(async (transaction) => {
195
+ await this.multiProvider.estimateGas(transaction.route.origin, transaction.populatedTx);
196
+ return transaction;
197
+ }));
198
+ // 2. Filter out failed transactions and log errors
199
+ const validTransactions = [];
200
+ let gasEstimationFailures = 0;
201
+ gasEstimateResults.forEach((result, i) => {
202
+ if (result.status === 'fulfilled') {
203
+ validTransactions.push(result.value);
204
+ }
205
+ else {
206
+ gasEstimationFailures++;
207
+ const failedTransaction = transactions[i];
208
+ this.logger.error({
209
+ origin: failedTransaction.route.origin,
210
+ destination: failedTransaction.route.destination,
211
+ amount: failedTransaction.originTokenAmount.getDecimalFormattedAmount(),
212
+ tokenName: failedTransaction.originTokenAmount.token.name,
213
+ error: result.reason,
214
+ }, 'Gas estimation failed for route.');
215
+ }
216
+ });
217
+ if (validTransactions.length === 0) {
218
+ this.logger.info('No transactions to execute after gas estimation.');
219
+ return {
220
+ gasEstimationFailures,
221
+ transactionFailures: 0,
222
+ successfulTransactions: [],
223
+ };
224
+ }
225
+ // 2. Send transactions
226
+ this.logger.info({ numTransactions: validTransactions.length }, 'Sending valid transactions.');
227
+ let transactionFailures = 0;
228
+ const successfulTransactions = [];
229
+ for (const transaction of validTransactions) {
230
+ try {
231
+ const { origin, destination } = transaction.route;
232
+ const decimalFormattedAmount = transaction.originTokenAmount.getDecimalFormattedAmount();
233
+ const tokenName = transaction.originTokenAmount.token.name;
234
+ this.logger.info({
235
+ origin,
236
+ destination,
237
+ amount: decimalFormattedAmount,
238
+ tokenName,
239
+ }, 'Sending transaction for route.');
240
+ const receipt = await this.multiProvider.sendTransaction(origin, transaction.populatedTx);
241
+ this.logger.info({
242
+ origin,
243
+ destination,
244
+ amount: decimalFormattedAmount,
245
+ tokenName,
246
+ txHash: receipt.transactionHash,
247
+ }, 'Transaction confirmed for route.');
248
+ successfulTransactions.push(transaction);
249
+ }
250
+ catch (error) {
251
+ transactionFailures++;
252
+ this.logger.error({
253
+ origin: transaction.route.origin,
254
+ destination: transaction.route.destination,
255
+ amount: transaction.originTokenAmount.getDecimalFormattedAmount(),
256
+ tokenName: transaction.originTokenAmount.token.name,
257
+ error,
258
+ }, 'Transaction failed for route.');
259
+ }
260
+ }
261
+ return {
262
+ gasEstimationFailures,
263
+ transactionFailures,
264
+ successfulTransactions,
265
+ };
266
+ }
267
+ filterTransactions(transactions) {
268
+ const filteredTransactions = [];
269
+ for (const transaction of transactions) {
270
+ const { origin, destination, amount } = transaction.route;
271
+ const originToken = this.tokensByChainName[origin];
272
+ const decimalFormattedAmount = transaction.originTokenAmount.getDecimalFormattedAmount();
273
+ // minimum amount check
274
+ const { bridgeMinAcceptedAmount } = getBridgeConfig(this.bridges, origin, destination, this.logger);
275
+ const minAccepted = BigInt(toWei(bridgeMinAcceptedAmount, originToken.decimals));
276
+ if (minAccepted > amount) {
277
+ this.logger.info({
278
+ origin,
279
+ destination,
280
+ amount: decimalFormattedAmount,
281
+ tokenName: originToken.name,
282
+ }, 'Route skipped due to minimum threshold amount not met.');
283
+ continue;
284
+ }
285
+ filteredTransactions.push(transaction);
286
+ }
287
+ return filteredTransactions;
288
+ }
289
+ }
290
+ //# sourceMappingURL=Rebalancer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Rebalancer.js","sourceRoot":"","sources":["../../src/core/Rebalancer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { Logger } from 'pino';
2
+ import { IRegistry } from '@hyperlane-xyz/registry';
3
+ import { type MultiProtocolProvider, type MultiProvider } from '@hyperlane-xyz/sdk';
4
+ import { RebalancerConfig } from '../config/RebalancerConfig.js';
5
+ export interface RebalancerServiceConfig {
6
+ /** Execution mode: 'manual' for one-off execution, 'daemon' for continuous monitoring */
7
+ mode: 'manual' | 'daemon';
8
+ /** Frequency to check balances in milliseconds (daemon mode only) */
9
+ checkFrequency?: number;
10
+ /** Enable monitor-only mode (no transactions executed) */
11
+ monitorOnly?: boolean;
12
+ /** Enable Prometheus metrics collection */
13
+ withMetrics?: boolean;
14
+ /** CoinGecko API key for token price fetching (required for metrics) */
15
+ coingeckoApiKey?: string;
16
+ /** Logger instance */
17
+ logger: Logger;
18
+ /** Service version for logging */
19
+ version?: string;
20
+ }
21
+ export interface ManualRebalanceRequest {
22
+ origin: string;
23
+ destination: string;
24
+ amount: string;
25
+ }
26
+ /**
27
+ * RebalancerService is the main orchestrator for the Hyperlane Warp Route Rebalancer.
28
+ * It supports both manual one-off rebalances and continuous daemon mode.
29
+ *
30
+ * @example Manual execution
31
+ * ```typescript
32
+ * const service = new RebalancerService(
33
+ * multiProvider,
34
+ * multiProtocolProvider,
35
+ * registry,
36
+ * rebalancerConfig,
37
+ * {
38
+ * mode: 'manual',
39
+ * logger: console,
40
+ * }
41
+ * );
42
+ * await service.executeManual({
43
+ * origin: 'ethereum',
44
+ * destination: 'arbitrum',
45
+ * amount: '1000',
46
+ * });
47
+ * ```
48
+ *
49
+ * @example Daemon mode
50
+ * ```typescript
51
+ * const service = new RebalancerService(
52
+ * multiProvider,
53
+ * multiProtocolProvider,
54
+ * registry,
55
+ * rebalancerConfig,
56
+ * {
57
+ * mode: 'daemon',
58
+ * checkFrequency: 60_000,
59
+ * withMetrics: true,
60
+ * coingeckoApiKey: process.env.COINGECKO_API_KEY,
61
+ * logger: console,
62
+ * }
63
+ * );
64
+ * await service.start();
65
+ * ```
66
+ */
67
+ export declare class RebalancerService {
68
+ private readonly multiProvider;
69
+ private readonly multiProtocolProvider;
70
+ private readonly registry;
71
+ private readonly rebalancerConfig;
72
+ private readonly config;
73
+ private isExiting;
74
+ private logger;
75
+ private contextFactory?;
76
+ private monitor?;
77
+ private strategy?;
78
+ private rebalancer?;
79
+ private metrics?;
80
+ private mode;
81
+ constructor(multiProvider: MultiProvider, multiProtocolProvider: MultiProtocolProvider | undefined, registry: IRegistry, rebalancerConfig: RebalancerConfig, config: RebalancerServiceConfig);
82
+ /**
83
+ * Initialize the service components
84
+ */
85
+ private initialize;
86
+ /**
87
+ * Execute a manual one-off rebalance
88
+ */
89
+ executeManual(request: ManualRebalanceRequest): Promise<void>;
90
+ /**
91
+ * Start the rebalancer in daemon mode (continuous monitoring)
92
+ */
93
+ start(): Promise<void>;
94
+ /**
95
+ * Stop the rebalancer daemon
96
+ */
97
+ stop(): Promise<void>;
98
+ /**
99
+ * Gracefully shutdown the service
100
+ */
101
+ gracefulShutdown(): Promise<void>;
102
+ /**
103
+ * Event handler for token info updates from monitor
104
+ */
105
+ private onTokenInfo;
106
+ /**
107
+ * Event handler for monitor errors
108
+ */
109
+ private onMonitorError;
110
+ /**
111
+ * Event handler for monitor start
112
+ */
113
+ private onMonitorStart;
114
+ }
115
+ //# sourceMappingURL=RebalancerService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RebalancerService.d.ts","sourceRoot":"","sources":["../../src/core/RebalancerService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAcjE,MAAM,WAAW,uBAAuB;IACtC,yFAAyF;IACzF,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAE1B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IAEf,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,iBAAiB;IAW1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAc;IACjC,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,IAAI,CAAsB;gBAGf,aAAa,EAAE,aAAa,EAC5B,qBAAqB,EAAE,qBAAqB,GAAG,SAAS,EACxD,QAAQ,EAAE,SAAS,EACnB,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,uBAAuB;IAMlD;;OAEG;YACW,UAAU;IA8CxB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDnE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBvC;;OAEG;YACW,WAAW;IA6BzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,cAAc;CAGvB"}
@@ -0,0 +1,227 @@
1
+ import { assert, toWei } from '@hyperlane-xyz/utils';
2
+ import { RebalancerContextFactory } from '../factories/RebalancerContextFactory.js';
3
+ import { MonitorEventType, MonitorPollingError, MonitorStartError, } from '../interfaces/IMonitor.js';
4
+ import { getRawBalances } from '../utils/balanceUtils.js';
5
+ /**
6
+ * RebalancerService is the main orchestrator for the Hyperlane Warp Route Rebalancer.
7
+ * It supports both manual one-off rebalances and continuous daemon mode.
8
+ *
9
+ * @example Manual execution
10
+ * ```typescript
11
+ * const service = new RebalancerService(
12
+ * multiProvider,
13
+ * multiProtocolProvider,
14
+ * registry,
15
+ * rebalancerConfig,
16
+ * {
17
+ * mode: 'manual',
18
+ * logger: console,
19
+ * }
20
+ * );
21
+ * await service.executeManual({
22
+ * origin: 'ethereum',
23
+ * destination: 'arbitrum',
24
+ * amount: '1000',
25
+ * });
26
+ * ```
27
+ *
28
+ * @example Daemon mode
29
+ * ```typescript
30
+ * const service = new RebalancerService(
31
+ * multiProvider,
32
+ * multiProtocolProvider,
33
+ * registry,
34
+ * rebalancerConfig,
35
+ * {
36
+ * mode: 'daemon',
37
+ * checkFrequency: 60_000,
38
+ * withMetrics: true,
39
+ * coingeckoApiKey: process.env.COINGECKO_API_KEY,
40
+ * logger: console,
41
+ * }
42
+ * );
43
+ * await service.start();
44
+ * ```
45
+ */
46
+ export class RebalancerService {
47
+ multiProvider;
48
+ multiProtocolProvider;
49
+ registry;
50
+ rebalancerConfig;
51
+ config;
52
+ isExiting = false;
53
+ logger;
54
+ contextFactory;
55
+ monitor;
56
+ strategy;
57
+ rebalancer;
58
+ metrics;
59
+ mode;
60
+ constructor(multiProvider, multiProtocolProvider, registry, rebalancerConfig, config) {
61
+ this.multiProvider = multiProvider;
62
+ this.multiProtocolProvider = multiProtocolProvider;
63
+ this.registry = registry;
64
+ this.rebalancerConfig = rebalancerConfig;
65
+ this.config = config;
66
+ this.logger = config.logger;
67
+ this.mode = config.mode;
68
+ }
69
+ /**
70
+ * Initialize the service components
71
+ */
72
+ async initialize() {
73
+ if (this.contextFactory) {
74
+ // Already initialized
75
+ return;
76
+ }
77
+ this.logger.info('Initializing RebalancerService...');
78
+ // Create context factory
79
+ this.contextFactory = await RebalancerContextFactory.create(this.rebalancerConfig, this.multiProvider, this.multiProtocolProvider, this.registry, this.logger);
80
+ // Create monitor (always needed for daemon mode)
81
+ if (this.mode === 'daemon') {
82
+ const checkFrequency = this.config.checkFrequency ?? 60000;
83
+ this.monitor = this.contextFactory.createMonitor(checkFrequency);
84
+ }
85
+ // Create metrics if enabled
86
+ if (this.config.withMetrics) {
87
+ this.metrics = await this.contextFactory.createMetrics(this.config.coingeckoApiKey);
88
+ this.logger.info('Metrics collection enabled');
89
+ }
90
+ // Create strategy
91
+ this.strategy = await this.contextFactory.createStrategy(this.metrics);
92
+ // Create rebalancer (unless in monitor-only mode)
93
+ if (!this.config.monitorOnly) {
94
+ this.rebalancer = this.contextFactory.createRebalancer(this.metrics);
95
+ }
96
+ else {
97
+ this.logger.warn('Running in monitorOnly mode: no transactions will be executed.');
98
+ }
99
+ this.logger.info('✅ RebalancerService initialized successfully');
100
+ }
101
+ /**
102
+ * Execute a manual one-off rebalance
103
+ */
104
+ async executeManual(request) {
105
+ await this.initialize();
106
+ assert(this.rebalancer, 'Rebalancer not available. MonitorOnly mode cannot execute manual rebalances.');
107
+ const { origin, destination, amount } = request;
108
+ this.logger.info(`Manual rebalance strategy selected. Origin: ${origin}, Destination: ${destination}, Amount: ${amount}`);
109
+ const warpCore = this.contextFactory.getWarpCore();
110
+ const originToken = warpCore.tokens.find((t) => t.chainName === origin);
111
+ if (!originToken) {
112
+ const error = `Origin token not found for chain ${origin}`;
113
+ this.logger.error(error);
114
+ throw new Error(error);
115
+ }
116
+ // Validate amount
117
+ const amountNum = Number(amount);
118
+ assert(!isNaN(amountNum), 'Amount must be a valid number');
119
+ assert(amountNum > 0, 'Amount must be greater than 0');
120
+ try {
121
+ await this.rebalancer.rebalance([
122
+ {
123
+ origin,
124
+ destination,
125
+ amount: BigInt(toWei(amount, originToken.decimals)),
126
+ },
127
+ ]);
128
+ this.logger.info(`✅ Manual rebalance from ${origin} to ${destination} for amount ${amount} submitted successfully.`);
129
+ }
130
+ catch (error) {
131
+ this.logger.error({ error }, `❌ Manual rebalance from ${origin} to ${destination} failed`);
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Start the rebalancer in daemon mode (continuous monitoring)
137
+ */
138
+ async start() {
139
+ if (this.mode !== 'daemon') {
140
+ throw new Error('start() can only be called in daemon mode');
141
+ }
142
+ await this.initialize();
143
+ assert(this.monitor, 'Monitor must be initialized for daemon mode');
144
+ // Setup monitor event listeners
145
+ this.monitor
146
+ .on(MonitorEventType.TokenInfo, this.onTokenInfo.bind(this))
147
+ .on(MonitorEventType.Error, this.onMonitorError.bind(this))
148
+ .on(MonitorEventType.Start, this.onMonitorStart.bind(this));
149
+ // Set up signal handlers for graceful shutdown
150
+ process.on('SIGINT', () => this.gracefulShutdown());
151
+ process.on('SIGTERM', () => this.gracefulShutdown());
152
+ try {
153
+ await this.monitor.start();
154
+ }
155
+ catch (error) {
156
+ this.logger.error({ error }, 'Rebalancer startup error');
157
+ throw error;
158
+ }
159
+ }
160
+ /**
161
+ * Stop the rebalancer daemon
162
+ */
163
+ async stop() {
164
+ if (this.monitor) {
165
+ await this.monitor.stop();
166
+ }
167
+ }
168
+ /**
169
+ * Gracefully shutdown the service
170
+ */
171
+ async gracefulShutdown() {
172
+ if (this.isExiting) {
173
+ return;
174
+ }
175
+ this.isExiting = true;
176
+ this.logger.info('Gracefully shutting down rebalancer...');
177
+ await this.stop();
178
+ // Unregister listeners to prevent them from being called again during shutdown
179
+ process.removeAllListeners('SIGINT');
180
+ process.removeAllListeners('SIGTERM');
181
+ this.logger.info('Rebalancer shutdown complete');
182
+ process.exit(0);
183
+ }
184
+ /**
185
+ * Event handler for token info updates from monitor
186
+ */
187
+ async onTokenInfo(event) {
188
+ if (this.metrics) {
189
+ await Promise.all(event.tokensInfo.map((tokenInfo) => this.metrics.processToken(tokenInfo)));
190
+ }
191
+ const rawBalances = getRawBalances(Object.keys(this.rebalancerConfig.strategyConfig.chains), event, this.logger);
192
+ const rebalancingRoutes = this.strategy.getRebalancingRoutes(rawBalances);
193
+ this.rebalancer
194
+ ?.rebalance(rebalancingRoutes)
195
+ .then(() => {
196
+ this.metrics?.recordRebalancerSuccess();
197
+ this.logger.info('Rebalancer completed a cycle successfully');
198
+ })
199
+ .catch((error) => {
200
+ this.metrics?.recordRebalancerFailure();
201
+ this.logger.error({ error }, 'Error while rebalancing');
202
+ });
203
+ }
204
+ /**
205
+ * Event handler for monitor errors
206
+ */
207
+ onMonitorError(error) {
208
+ if (error instanceof MonitorPollingError) {
209
+ this.logger.error(error.message);
210
+ this.metrics?.recordPollingError();
211
+ }
212
+ else if (error instanceof MonitorStartError) {
213
+ this.logger.error(error.message);
214
+ throw error;
215
+ }
216
+ else {
217
+ this.logger.error({ error }, 'An unexpected error occurred in the monitor');
218
+ }
219
+ }
220
+ /**
221
+ * Event handler for monitor start
222
+ */
223
+ onMonitorStart() {
224
+ this.logger.info('Rebalancer started successfully 🚀');
225
+ }
226
+ }
227
+ //# sourceMappingURL=RebalancerService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RebalancerService.js","sourceRoot":"","sources":["../../src/core/RebalancerService.ts"],"names":[],"mappings":"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"}