@hyperlane-xyz/rebalancer 0.1.2 → 1.0.0
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.
- package/README.md +134 -14
- package/dist/config/RebalancerConfig.d.ts +2 -2
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +4 -3
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +434 -163
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +1650 -290
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +124 -46
- package/dist/config/types.js.map +1 -1
- package/dist/core/Rebalancer.d.ts +14 -7
- package/dist/core/Rebalancer.d.ts.map +1 -1
- package/dist/core/Rebalancer.js +168 -99
- package/dist/core/Rebalancer.js.map +1 -1
- package/dist/core/Rebalancer.test.d.ts +2 -0
- package/dist/core/Rebalancer.test.d.ts.map +1 -0
- package/dist/core/Rebalancer.test.js +391 -0
- package/dist/core/Rebalancer.test.js.map +1 -0
- package/dist/core/RebalancerService.d.ts +16 -2
- package/dist/core/RebalancerService.d.ts.map +1 -1
- package/dist/core/RebalancerService.js +164 -21
- package/dist/core/RebalancerService.js.map +1 -1
- package/dist/core/RebalancerService.test.d.ts +2 -0
- package/dist/core/RebalancerService.test.d.ts.map +1 -0
- package/dist/core/RebalancerService.test.js +809 -0
- package/dist/core/RebalancerService.test.js.map +1 -0
- package/dist/factories/RebalancerContextFactory.d.ts +11 -0
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
- package/dist/factories/RebalancerContextFactory.js +60 -13
- package/dist/factories/RebalancerContextFactory.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IMonitor.d.ts +6 -8
- package/dist/interfaces/IMonitor.d.ts.map +1 -1
- package/dist/interfaces/IMonitor.js.map +1 -1
- package/dist/interfaces/IRebalancer.d.ts +20 -4
- package/dist/interfaces/IRebalancer.d.ts.map +1 -1
- package/dist/interfaces/IStrategy.d.ts +18 -2
- package/dist/interfaces/IStrategy.d.ts.map +1 -1
- package/dist/metrics/Metrics.d.ts +4 -2
- package/dist/metrics/Metrics.d.ts.map +1 -1
- package/dist/metrics/Metrics.js +21 -1
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/metrics/scripts/metrics.d.ts +2 -0
- package/dist/metrics/scripts/metrics.d.ts.map +1 -1
- package/dist/metrics/scripts/metrics.js +12 -0
- package/dist/metrics/scripts/metrics.js.map +1 -1
- package/dist/monitor/Monitor.d.ts +8 -3
- package/dist/monitor/Monitor.d.ts.map +1 -1
- package/dist/monitor/Monitor.js +75 -15
- package/dist/monitor/Monitor.js.map +1 -1
- package/dist/strategy/BaseStrategy.d.ts +51 -5
- package/dist/strategy/BaseStrategy.d.ts.map +1 -1
- package/dist/strategy/BaseStrategy.js +199 -19
- package/dist/strategy/BaseStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts +65 -0
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -0
- package/dist/strategy/CollateralDeficitStrategy.js +245 -0
- package/dist/strategy/CollateralDeficitStrategy.js.map +1 -0
- package/dist/strategy/CollateralDeficitStrategy.test.d.ts +2 -0
- package/dist/strategy/CollateralDeficitStrategy.test.d.ts.map +1 -0
- package/dist/strategy/CollateralDeficitStrategy.test.js +364 -0
- package/dist/strategy/CollateralDeficitStrategy.test.js.map +1 -0
- package/dist/strategy/CompositeStrategy.d.ts +18 -0
- package/dist/strategy/CompositeStrategy.d.ts.map +1 -0
- package/dist/strategy/CompositeStrategy.js +63 -0
- package/dist/strategy/CompositeStrategy.js.map +1 -0
- package/dist/strategy/CompositeStrategy.test.d.ts +2 -0
- package/dist/strategy/CompositeStrategy.test.d.ts.map +1 -0
- package/dist/strategy/CompositeStrategy.test.js +265 -0
- package/dist/strategy/CompositeStrategy.test.js.map +1 -0
- package/dist/strategy/MinAmountStrategy.d.ts +12 -5
- package/dist/strategy/MinAmountStrategy.d.ts.map +1 -1
- package/dist/strategy/MinAmountStrategy.js +23 -14
- package/dist/strategy/MinAmountStrategy.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.test.js +88 -20
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
- package/dist/strategy/StrategyFactory.d.ts +15 -6
- package/dist/strategy/StrategyFactory.d.ts.map +1 -1
- package/dist/strategy/StrategyFactory.js +48 -10
- package/dist/strategy/StrategyFactory.js.map +1 -1
- package/dist/strategy/StrategyFactory.test.js +2 -2
- package/dist/strategy/StrategyFactory.test.js.map +1 -1
- package/dist/strategy/WeightedStrategy.d.ts +13 -4
- package/dist/strategy/WeightedStrategy.d.ts.map +1 -1
- package/dist/strategy/WeightedStrategy.js +18 -6
- package/dist/strategy/WeightedStrategy.js.map +1 -1
- package/dist/strategy/WeightedStrategy.test.js +108 -18
- package/dist/strategy/WeightedStrategy.test.js.map +1 -1
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.d.ts.map +1 -1
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/index.js.map +1 -1
- package/dist/test/helpers.d.ts +93 -3
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +267 -10
- package/dist/test/helpers.js.map +1 -1
- package/dist/tracking/ActionTracker.d.ts +49 -0
- package/dist/tracking/ActionTracker.d.ts.map +1 -0
- package/dist/tracking/ActionTracker.js +422 -0
- package/dist/tracking/ActionTracker.js.map +1 -0
- package/dist/tracking/ActionTracker.test.d.ts +2 -0
- package/dist/tracking/ActionTracker.test.d.ts.map +1 -0
- package/dist/tracking/ActionTracker.test.js +637 -0
- package/dist/tracking/ActionTracker.test.js.map +1 -0
- package/dist/tracking/IActionTracker.d.ts +101 -0
- package/dist/tracking/IActionTracker.d.ts.map +1 -0
- package/dist/tracking/IActionTracker.js +2 -0
- package/dist/tracking/IActionTracker.js.map +1 -0
- package/dist/tracking/InflightContextAdapter.d.ts +18 -0
- package/dist/tracking/InflightContextAdapter.d.ts.map +1 -0
- package/dist/tracking/InflightContextAdapter.js +35 -0
- package/dist/tracking/InflightContextAdapter.js.map +1 -0
- package/dist/tracking/InflightContextAdapter.test.d.ts +2 -0
- package/dist/tracking/InflightContextAdapter.test.d.ts.map +1 -0
- package/dist/tracking/InflightContextAdapter.test.js +172 -0
- package/dist/tracking/InflightContextAdapter.test.js.map +1 -0
- package/dist/tracking/index.d.ts +7 -0
- package/dist/tracking/index.d.ts.map +1 -0
- package/dist/tracking/index.js +6 -0
- package/dist/tracking/index.js.map +1 -0
- package/dist/tracking/store/IStore.d.ts +41 -0
- package/dist/tracking/store/IStore.d.ts.map +1 -0
- package/dist/tracking/store/IStore.js +2 -0
- package/dist/tracking/store/IStore.js.map +1 -0
- package/dist/tracking/store/InMemoryStore.d.ts +21 -0
- package/dist/tracking/store/InMemoryStore.d.ts.map +1 -0
- package/dist/tracking/store/InMemoryStore.js +40 -0
- package/dist/tracking/store/InMemoryStore.js.map +1 -0
- package/dist/tracking/store/InMemoryStore.test.d.ts +2 -0
- package/dist/tracking/store/InMemoryStore.test.d.ts.map +1 -0
- package/dist/tracking/store/InMemoryStore.test.js +290 -0
- package/dist/tracking/store/InMemoryStore.test.js.map +1 -0
- package/dist/tracking/store/index.d.ts +3 -0
- package/dist/tracking/store/index.d.ts.map +1 -0
- package/dist/tracking/store/index.js +2 -0
- package/dist/tracking/store/index.js.map +1 -0
- package/dist/tracking/types.d.ts +43 -0
- package/dist/tracking/types.d.ts.map +1 -0
- package/dist/tracking/types.js +2 -0
- package/dist/tracking/types.js.map +1 -0
- package/dist/utils/ExplorerClient.d.ts +39 -1
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +205 -2
- package/dist/utils/ExplorerClient.js.map +1 -1
- package/dist/utils/balanceUtils.js +2 -2
- package/dist/utils/balanceUtils.js.map +1 -1
- package/dist/utils/balanceUtils.test.js +1 -0
- package/dist/utils/balanceUtils.test.js.map +1 -1
- package/dist/utils/bridgeUtils.d.ts +1 -3
- package/dist/utils/bridgeUtils.d.ts.map +1 -1
- package/dist/utils/bridgeUtils.js +1 -5
- package/dist/utils/bridgeUtils.js.map +1 -1
- package/dist/utils/bridgeUtils.test.js +3 -14
- package/dist/utils/bridgeUtils.test.js.map +1 -1
- package/package.json +11 -9
- package/src/config/RebalancerConfig.test.ts +459 -163
- package/src/config/RebalancerConfig.ts +5 -3
- package/src/config/types.ts +159 -52
- package/src/core/Rebalancer.test.ts +632 -0
- package/src/core/Rebalancer.ts +247 -157
- package/src/core/RebalancerService.test.ts +1144 -0
- package/src/core/RebalancerService.ts +245 -23
- package/src/factories/RebalancerContextFactory.ts +115 -14
- package/src/index.ts +16 -4
- package/src/interfaces/IMonitor.ts +15 -8
- package/src/interfaces/IRebalancer.ts +22 -4
- package/src/interfaces/IStrategy.ts +23 -2
- package/src/metrics/Metrics.ts +26 -5
- package/src/metrics/scripts/metrics.ts +14 -0
- package/src/monitor/Monitor.ts +109 -22
- package/src/strategy/BaseStrategy.ts +316 -26
- package/src/strategy/CollateralDeficitStrategy.test.ts +551 -0
- package/src/strategy/CollateralDeficitStrategy.ts +390 -0
- package/src/strategy/CompositeStrategy.test.ts +405 -0
- package/src/strategy/CompositeStrategy.ts +102 -0
- package/src/strategy/MinAmountStrategy.test.ts +189 -88
- package/src/strategy/MinAmountStrategy.ts +44 -13
- package/src/strategy/StrategyFactory.test.ts +2 -2
- package/src/strategy/StrategyFactory.ts +91 -8
- package/src/strategy/WeightedStrategy.test.ts +187 -72
- package/src/strategy/WeightedStrategy.ts +41 -7
- package/src/strategy/index.ts +2 -0
- package/src/test/helpers.ts +418 -14
- package/src/tracking/ActionTracker.test.ts +783 -0
- package/src/tracking/ActionTracker.ts +647 -0
- package/src/tracking/IActionTracker.ts +140 -0
- package/src/tracking/InflightContextAdapter.test.ts +203 -0
- package/src/tracking/InflightContextAdapter.ts +42 -0
- package/src/tracking/index.ts +36 -0
- package/src/tracking/store/IStore.ts +48 -0
- package/src/tracking/store/InMemoryStore.test.ts +338 -0
- package/src/tracking/store/InMemoryStore.ts +58 -0
- package/src/tracking/store/index.ts +2 -0
- package/src/tracking/types.ts +74 -0
- package/src/utils/ExplorerClient.ts +266 -3
- package/src/utils/balanceUtils.test.ts +1 -0
- package/src/utils/balanceUtils.ts +2 -2
- package/src/utils/bridgeUtils.test.ts +3 -15
- package/src/utils/bridgeUtils.ts +0 -10
- package/dist/core/WithInflightGuard.d.ts +0 -20
- package/dist/core/WithInflightGuard.d.ts.map +0 -1
- package/dist/core/WithInflightGuard.js +0 -47
- package/dist/core/WithInflightGuard.js.map +0 -1
- package/dist/core/WithInflightGuard.test.d.ts +0 -2
- package/dist/core/WithInflightGuard.test.d.ts.map +0 -1
- package/dist/core/WithInflightGuard.test.js +0 -64
- package/dist/core/WithInflightGuard.test.js.map +0 -1
- package/dist/core/WithSemaphore.d.ts +0 -22
- package/dist/core/WithSemaphore.d.ts.map +0 -1
- package/dist/core/WithSemaphore.js +0 -67
- package/dist/core/WithSemaphore.js.map +0 -1
- package/dist/core/WithSemaphore.test.d.ts +0 -2
- package/dist/core/WithSemaphore.test.d.ts.map +0 -1
- package/dist/core/WithSemaphore.test.js +0 -83
- package/dist/core/WithSemaphore.test.js.map +0 -1
- package/src/core/WithInflightGuard.test.ts +0 -131
- package/src/core/WithInflightGuard.ts +0 -67
- package/src/core/WithSemaphore.test.ts +0 -111
- package/src/core/WithSemaphore.ts +0 -92
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { type Logger } from 'pino';
|
|
2
|
-
import type
|
|
2
|
+
import { type WarpCore } from '@hyperlane-xyz/sdk';
|
|
3
3
|
import { type IMonitor, type MonitorEvent, MonitorEventType } from '../interfaces/IMonitor.js';
|
|
4
4
|
/**
|
|
5
5
|
* Simple monitor implementation that polls warp route collateral balances and emits them as MonitorEvent.
|
|
6
|
+
* Awaits the TokenInfo handler before starting the next cycle to prevent race conditions.
|
|
6
7
|
*/
|
|
7
8
|
export declare class Monitor implements IMonitor {
|
|
8
9
|
private readonly checkFrequency;
|
|
9
10
|
private readonly warpCore;
|
|
10
11
|
private readonly logger;
|
|
11
|
-
private
|
|
12
|
+
private tokenInfoHandler?;
|
|
13
|
+
private errorHandler?;
|
|
14
|
+
private startHandler?;
|
|
12
15
|
private isMonitorRunning;
|
|
13
16
|
private resolveStop;
|
|
14
17
|
private stopPromise;
|
|
@@ -16,7 +19,9 @@ export declare class Monitor implements IMonitor {
|
|
|
16
19
|
* @param checkFrequency - The frequency to poll balances in ms.
|
|
17
20
|
*/
|
|
18
21
|
constructor(checkFrequency: number, warpCore: WarpCore, logger: Logger);
|
|
19
|
-
|
|
22
|
+
private getConfirmedBlockTag;
|
|
23
|
+
private computeConfirmedBlockTags;
|
|
24
|
+
on(eventName: MonitorEventType.TokenInfo, fn: (event: MonitorEvent) => void | Promise<void>): this;
|
|
20
25
|
on(eventName: MonitorEventType.Error, fn: (event: Error) => void): this;
|
|
21
26
|
on(eventName: MonitorEventType.Start, fn: () => void): this;
|
|
22
27
|
start(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Monitor.d.ts","sourceRoot":"","sources":["../../src/monitor/Monitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Monitor.d.ts","sourceRoot":"","sources":["../../src/monitor/Monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,gBAAgB,EAGjB,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,qBAAa,OAAQ,YAAW,QAAQ;IAYpC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,OAAO,CAAC,gBAAgB,CAAC,CAAgD;IACzE,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,WAAW,CAA8B;IAEjD;;OAEG;gBAEgB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM;YAGnB,oBAAoB;YAwBpB,yBAAyB;IAYvC,EAAE,CACA,SAAS,EAAE,gBAAgB,CAAC,SAAS,EACrC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAChD,IAAI;IACP,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IACvE,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IAkBrD,KAAK;YA6FG,qBAAqB;IAmDnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAiBtB"}
|
package/dist/monitor/Monitor.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
2
1
|
import { sleep } from '@hyperlane-xyz/utils';
|
|
3
2
|
import { MonitorEventType, MonitorPollingError, MonitorStartError, } from '../interfaces/IMonitor.js';
|
|
4
3
|
/**
|
|
5
4
|
* Simple monitor implementation that polls warp route collateral balances and emits them as MonitorEvent.
|
|
5
|
+
* Awaits the TokenInfo handler before starting the next cycle to prevent race conditions.
|
|
6
6
|
*/
|
|
7
7
|
export class Monitor {
|
|
8
8
|
checkFrequency;
|
|
9
9
|
warpCore;
|
|
10
10
|
logger;
|
|
11
|
-
|
|
11
|
+
tokenInfoHandler;
|
|
12
|
+
errorHandler;
|
|
13
|
+
startHandler;
|
|
12
14
|
isMonitorRunning = false;
|
|
13
15
|
resolveStop = null;
|
|
14
16
|
stopPromise = null;
|
|
@@ -20,25 +22,62 @@ export class Monitor {
|
|
|
20
22
|
this.warpCore = warpCore;
|
|
21
23
|
this.logger = logger;
|
|
22
24
|
}
|
|
25
|
+
async getConfirmedBlockTag(chainName) {
|
|
26
|
+
try {
|
|
27
|
+
const metadata = this.warpCore.multiProvider.getChainMetadata(chainName);
|
|
28
|
+
const reorgPeriod = metadata.blocks?.reorgPeriod ?? 32;
|
|
29
|
+
if (typeof reorgPeriod === 'string') {
|
|
30
|
+
return reorgPeriod;
|
|
31
|
+
}
|
|
32
|
+
const provider = this.warpCore.multiProvider.getEthersV5Provider(chainName);
|
|
33
|
+
const latestBlock = await provider.getBlockNumber();
|
|
34
|
+
return Math.max(0, latestBlock - reorgPeriod);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.logger.warn({ chain: chainName, error: error.message }, 'Failed to get confirmed block, using latest');
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async computeConfirmedBlockTags() {
|
|
42
|
+
const blockTags = {};
|
|
43
|
+
const chains = new Set(this.warpCore.tokens.map((t) => t.chainName));
|
|
44
|
+
for (const chain of chains) {
|
|
45
|
+
blockTags[chain] = await this.getConfirmedBlockTag(chain);
|
|
46
|
+
}
|
|
47
|
+
return blockTags;
|
|
48
|
+
}
|
|
23
49
|
on(eventName, fn) {
|
|
24
|
-
|
|
50
|
+
switch (eventName) {
|
|
51
|
+
case MonitorEventType.TokenInfo:
|
|
52
|
+
this.tokenInfoHandler = fn;
|
|
53
|
+
break;
|
|
54
|
+
case MonitorEventType.Error:
|
|
55
|
+
this.errorHandler = fn;
|
|
56
|
+
break;
|
|
57
|
+
case MonitorEventType.Start:
|
|
58
|
+
this.startHandler = fn;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
25
61
|
return this;
|
|
26
62
|
}
|
|
27
63
|
async start() {
|
|
28
64
|
if (this.isMonitorRunning) {
|
|
29
65
|
// Cannot start the same monitor multiple times
|
|
30
|
-
this.
|
|
66
|
+
this.errorHandler?.(new MonitorStartError('Monitor already running'));
|
|
31
67
|
return;
|
|
32
68
|
}
|
|
33
69
|
try {
|
|
34
70
|
this.isMonitorRunning = true;
|
|
35
71
|
this.logger.debug({ checkFrequency: this.checkFrequency }, 'Monitor started');
|
|
36
|
-
this.
|
|
72
|
+
this.startHandler?.();
|
|
37
73
|
while (this.isMonitorRunning) {
|
|
74
|
+
const cycleStart = Date.now();
|
|
38
75
|
try {
|
|
39
76
|
this.logger.debug('Polling cycle started');
|
|
77
|
+
const confirmedBlockTags = await this.computeConfirmedBlockTags();
|
|
40
78
|
const event = {
|
|
41
79
|
tokensInfo: [],
|
|
80
|
+
confirmedBlockTags,
|
|
42
81
|
};
|
|
43
82
|
for (const token of this.warpCore.tokens) {
|
|
44
83
|
this.logger.debug({
|
|
@@ -46,28 +85,37 @@ export class Monitor {
|
|
|
46
85
|
tokenSymbol: token.symbol,
|
|
47
86
|
tokenAddress: token.addressOrDenom,
|
|
48
87
|
}, 'Checking token');
|
|
49
|
-
const
|
|
88
|
+
const blockTag = confirmedBlockTags[token.chainName];
|
|
89
|
+
const bridgedSupply = await this.getTokenBridgedSupply(token, blockTag);
|
|
50
90
|
event.tokensInfo.push({
|
|
51
91
|
token,
|
|
52
92
|
bridgedSupply,
|
|
53
93
|
});
|
|
54
94
|
}
|
|
55
|
-
|
|
56
|
-
|
|
95
|
+
if (this.tokenInfoHandler) {
|
|
96
|
+
await this.tokenInfoHandler(event);
|
|
97
|
+
}
|
|
57
98
|
this.logger.debug('Polling cycle completed');
|
|
58
99
|
}
|
|
59
100
|
catch (error) {
|
|
60
|
-
this.
|
|
101
|
+
this.errorHandler?.(new MonitorPollingError(`Error during monitor execution cycle: ${error.message}`, error));
|
|
102
|
+
}
|
|
103
|
+
// Smart sleep: only wait for remaining time after cycle completes
|
|
104
|
+
const elapsed = Date.now() - cycleStart;
|
|
105
|
+
const remaining = this.checkFrequency - elapsed;
|
|
106
|
+
if (remaining > 0) {
|
|
107
|
+
await sleep(remaining);
|
|
61
108
|
}
|
|
62
|
-
//
|
|
63
|
-
await sleep(this.checkFrequency);
|
|
109
|
+
// If elapsed >= checkFrequency, start next cycle immediately
|
|
64
110
|
}
|
|
65
111
|
}
|
|
66
112
|
catch (error) {
|
|
67
|
-
this.
|
|
113
|
+
this.errorHandler?.(new MonitorStartError(`Error starting monitor: ${error.message}`, error));
|
|
68
114
|
}
|
|
69
115
|
// After the loop has been gracefully terminated, we can clean up.
|
|
70
|
-
this.
|
|
116
|
+
this.tokenInfoHandler = undefined;
|
|
117
|
+
this.errorHandler = undefined;
|
|
118
|
+
this.startHandler = undefined;
|
|
71
119
|
this.logger.info('Monitor stopped');
|
|
72
120
|
// If stop() was called, resolve the promise to signal that we're done.
|
|
73
121
|
if (this.resolveStop) {
|
|
@@ -76,7 +124,7 @@ export class Monitor {
|
|
|
76
124
|
this.stopPromise = null;
|
|
77
125
|
}
|
|
78
126
|
}
|
|
79
|
-
async getTokenBridgedSupply(token) {
|
|
127
|
+
async getTokenBridgedSupply(token, blockTag) {
|
|
80
128
|
if (!token.isHypToken()) {
|
|
81
129
|
this.logger.warn({
|
|
82
130
|
chain: token.chainName,
|
|
@@ -86,7 +134,19 @@ export class Monitor {
|
|
|
86
134
|
return;
|
|
87
135
|
}
|
|
88
136
|
const adapter = token.getHypAdapter(this.warpCore.multiProvider);
|
|
89
|
-
|
|
137
|
+
let bridgedSupply;
|
|
138
|
+
try {
|
|
139
|
+
bridgedSupply = await adapter.getBridgedSupply({ blockTag });
|
|
140
|
+
this.logger.debug({ chain: token.chainName, blockTag }, 'Queried confirmed balance');
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
this.logger.warn({
|
|
144
|
+
chain: token.chainName,
|
|
145
|
+
blockTag,
|
|
146
|
+
error: error.message,
|
|
147
|
+
}, 'Historical block query failed, falling back to latest');
|
|
148
|
+
bridgedSupply = await adapter.getBridgedSupply();
|
|
149
|
+
}
|
|
90
150
|
if (bridgedSupply === undefined) {
|
|
91
151
|
this.logger.warn({
|
|
92
152
|
chain: token.chainName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Monitor.js","sourceRoot":"","sources":["../../src/monitor/Monitor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Monitor.js","sourceRoot":"","sources":["../../src/monitor/Monitor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAKL,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,MAAM,OAAO,OAAO;IAYC;IACA;IACA;IAbX,gBAAgB,CAAiD;IACjE,YAAY,CAA0B;IACtC,YAAY,CAAc;IAC1B,gBAAgB,GAAG,KAAK,CAAC;IACzB,WAAW,GAAwB,IAAI,CAAC;IACxC,WAAW,GAAyB,IAAI,CAAC;IAEjD;;OAEG;IACH,YACmB,cAAsB,EACtB,QAAkB,EAClB,MAAc;QAFd,mBAAc,GAAd,cAAc,CAAQ;QACtB,aAAQ,GAAR,QAAQ,CAAU;QAClB,WAAM,GAAN,MAAM,CAAQ;IAC9B,CAAC;IAEI,KAAK,CAAC,oBAAoB,CAChC,SAAiB;QAEjB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YACzE,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC;YAEvD,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;gBACpC,OAAO,WAA0C,CAAC;YACpD,CAAC;YAED,MAAM,QAAQ,GACZ,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;YAC7D,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,EACrD,6CAA6C,CAC9C,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,yBAAyB;QACrC,MAAM,SAAS,GAAuB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAErE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IASD,EAAE,CAAC,SAAiB,EAAE,EAA4C;QAChE,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,gBAAgB,CAAC,SAAS;gBAC7B,IAAI,CAAC,gBAAgB,GAAG,EAEC,CAAC;gBAC1B,MAAM;YACR,KAAK,gBAAgB,CAAC,KAAK;gBACzB,IAAI,CAAC,YAAY,GAAG,EAA4B,CAAC;gBACjD,MAAM;YACR,KAAK,gBAAgB,CAAC,KAAK;gBACzB,IAAI,CAAC,YAAY,GAAG,EAAgB,CAAC;gBACrC,MAAM;QACV,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,+CAA+C;YAC/C,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,iBAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,EACvC,iBAAiB,CAClB,CAAC;YACF,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YAEtB,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAE9B,IAAI,CAAC;oBACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;oBAE3C,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAC;oBAElE,MAAM,KAAK,GAAiB;wBAC1B,UAAU,EAAE,EAAE;wBACd,kBAAkB;qBACnB,CAAC;oBAEF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;wBACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CACf;4BACE,KAAK,EAAE,KAAK,CAAC,SAAS;4BACtB,WAAW,EAAE,KAAK,CAAC,MAAM;4BACzB,YAAY,EAAE,KAAK,CAAC,cAAc;yBACnC,EACD,gBAAgB,CACjB,CAAC;wBACF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;wBACrD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CACpD,KAAK,EACL,QAAQ,CACT,CAAC;wBAEF,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;4BACpB,KAAK;4BACL,aAAa;yBACd,CAAC,CAAC;oBACL,CAAC;oBAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBAC1B,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;oBACrC,CAAC;oBACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBAC/C,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,YAAY,EAAE,CACjB,IAAI,mBAAmB,CACrB,yCAA0C,KAAe,CAAC,OAAO,EAAE,EACnE,KAAc,CACf,CACF,CAAC;gBACJ,CAAC;gBAED,kEAAkE;gBAClE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;gBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;gBAChD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;oBAClB,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;gBACzB,CAAC;gBACD,6DAA6D;YAC/D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,YAAY,EAAE,CACjB,IAAI,iBAAiB,CACnB,2BAA4B,KAAe,CAAC,OAAO,EAAE,EACrD,KAAc,CACf,CACF,CAAC;QACJ,CAAC;QAED,kEAAkE;QAClE,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAEpC,uEAAuE;QACvE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,KAAY,EACZ,QAA4B;QAE5B,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,WAAW,EAAE,KAAK,CAAC,MAAM;gBACzB,YAAY,EAAE,KAAK,CAAC,cAAc;aACnC,EACD,sDAAsD,CACvD,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACjE,IAAI,aAAiC,CAAC;QAEtC,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,EACpC,2BAA2B,CAC5B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,QAAQ;gBACR,KAAK,EAAG,KAAe,CAAC,OAAO;aAChC,EACD,uDAAuD,CACxD,CAAC;YACF,aAAa,GAAG,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACnD,CAAC;QAED,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,WAAW,EAAE,KAAK,CAAC,MAAM;gBACzB,YAAY,EAAE,KAAK,CAAC,cAAc;aACnC,EACD,oCAAoC,CACrC,CAAC;QACJ,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAErD,8DAA8D;QAC9D,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACxC,iEAAiE;QACjE,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAE9B,+DAA+D;QAC/D,0CAA0C;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACzC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type Logger } from 'pino';
|
|
2
|
-
import type { ChainName } from '@hyperlane-xyz/sdk';
|
|
3
|
-
import type { IStrategy, RawBalances,
|
|
2
|
+
import type { ChainMap, ChainName, Token } from '@hyperlane-xyz/sdk';
|
|
3
|
+
import type { IStrategy, InflightContext, RawBalances, Route, StrategyRoute } from '../interfaces/IStrategy.js';
|
|
4
4
|
import { type Metrics } from '../metrics/Metrics.js';
|
|
5
|
+
import { type BridgeConfig, type BridgeConfigWithOverride } from '../utils/bridgeUtils.js';
|
|
5
6
|
export type Delta = {
|
|
6
7
|
chain: ChainName;
|
|
7
8
|
amount: bigint;
|
|
@@ -10,19 +11,28 @@ export type Delta = {
|
|
|
10
11
|
* Base abstract class for rebalancing strategies
|
|
11
12
|
*/
|
|
12
13
|
export declare abstract class BaseStrategy implements IStrategy {
|
|
14
|
+
abstract readonly name: string;
|
|
13
15
|
protected readonly chains: ChainName[];
|
|
14
16
|
protected readonly metrics?: Metrics;
|
|
15
17
|
protected readonly logger: Logger;
|
|
16
|
-
|
|
18
|
+
protected readonly bridgeConfigs: ChainMap<BridgeConfigWithOverride>;
|
|
19
|
+
protected readonly tokensByChainName?: ChainMap<Token>;
|
|
20
|
+
constructor(chains: ChainName[], logger: Logger, bridgeConfigs: ChainMap<BridgeConfigWithOverride>, metrics?: Metrics, tokensByChainName?: ChainMap<Token>);
|
|
21
|
+
protected getBridgeConfigForRoute(origin: ChainName, destination: ChainName): BridgeConfig;
|
|
17
22
|
/**
|
|
18
23
|
* Main method to get rebalancing routes
|
|
19
24
|
*/
|
|
20
|
-
getRebalancingRoutes(rawBalances: RawBalances):
|
|
25
|
+
getRebalancingRoutes(rawBalances: RawBalances, inflightContext?: InflightContext): StrategyRoute[];
|
|
21
26
|
/**
|
|
22
27
|
* Abstract method to get balances categorized by surplus and deficit
|
|
23
28
|
* Each specific strategy should implement its own logic
|
|
29
|
+
*
|
|
30
|
+
* @param balances - Effective balances (after collateral reservation)
|
|
31
|
+
* @param pendingRebalances - In-flight rebalances (origin tx confirmed, balance already deducted)
|
|
32
|
+
* @param proposedRebalances - Routes from earlier strategies in same cycle (not yet executed)
|
|
33
|
+
* @returns Categorized surpluses and deficits as Delta arrays
|
|
24
34
|
*/
|
|
25
|
-
protected abstract getCategorizedBalances(
|
|
35
|
+
protected abstract getCategorizedBalances(balances: RawBalances, pendingRebalances?: Route[], proposedRebalances?: StrategyRoute[]): {
|
|
26
36
|
surpluses: Delta[];
|
|
27
37
|
deficits: Delta[];
|
|
28
38
|
};
|
|
@@ -30,5 +40,41 @@ export declare abstract class BaseStrategy implements IStrategy {
|
|
|
30
40
|
* Validates the raw balances against the chains configuration
|
|
31
41
|
*/
|
|
32
42
|
protected validateRawBalances(rawBalances: RawBalances): void;
|
|
43
|
+
/**
|
|
44
|
+
* Reserve collateral for pending user transfers.
|
|
45
|
+
* Subtracts pending transfer amounts from destination balances.
|
|
46
|
+
* This ensures we don't drain collateral needed for incoming transfers.
|
|
47
|
+
*
|
|
48
|
+
* @param rawBalances - Current on-chain balances
|
|
49
|
+
* @param pendingTransfers - Transfers that will need collateral on destination
|
|
50
|
+
* @returns Balances with reserved amounts subtracted
|
|
51
|
+
*/
|
|
52
|
+
protected reserveCollateral(rawBalances: RawBalances, pendingTransfers: Route[]): RawBalances;
|
|
53
|
+
/**
|
|
54
|
+
* Simulate pending rebalances by adding to destination balances.
|
|
55
|
+
*
|
|
56
|
+
* Only adds to destination - does NOT subtract from origin because:
|
|
57
|
+
* - pendingRebalances only contains in_progress intents (origin tx confirmed)
|
|
58
|
+
* - Origin balance is already deducted on-chain
|
|
59
|
+
*
|
|
60
|
+
* @param rawBalances - Current balances (may already have collateral reserved)
|
|
61
|
+
* @param pendingRebalances - In-flight rebalance operations (in_progress only)
|
|
62
|
+
* @returns Simulated future balances after rebalances complete
|
|
63
|
+
*/
|
|
64
|
+
protected simulatePendingRebalances(rawBalances: RawBalances, pendingRebalances: Route[]): RawBalances;
|
|
65
|
+
/**
|
|
66
|
+
* Simulate proposed rebalances by subtracting from origin AND adding to destination.
|
|
67
|
+
*
|
|
68
|
+
* Unlike pendingRebalances, proposedRebalances are routes from earlier strategies
|
|
69
|
+
* in the same cycle that haven't been executed yet. Therefore:
|
|
70
|
+
* - Origin balance has NOT been deducted on-chain
|
|
71
|
+
* - We must simulate both sides to maintain accurate total balance
|
|
72
|
+
*
|
|
73
|
+
* @param rawBalances - Current balances (may already have pending rebalances simulated)
|
|
74
|
+
* @param proposedRebalances - Routes from earlier strategies (not yet executed)
|
|
75
|
+
* @returns Simulated balances after proposed rebalances complete
|
|
76
|
+
*/
|
|
77
|
+
protected simulateProposedRebalances(rawBalances: RawBalances, proposedRebalances: Route[]): RawBalances;
|
|
78
|
+
protected filterRoutes(routes: StrategyRoute[], actualBalances: RawBalances): StrategyRoute[];
|
|
33
79
|
}
|
|
34
80
|
//# sourceMappingURL=BaseStrategy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStrategy.d.ts","sourceRoot":"","sources":["../../src/strategy/BaseStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseStrategy.d.ts","sourceRoot":"","sources":["../../src/strategy/BaseStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGrE,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,KAAK,EACL,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAE9B,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,KAAK,GAAG;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;GAEG;AACH,8BAAsB,YAAa,YAAW,SAAS;IACrD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IACrE,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAGrD,MAAM,EAAE,SAAS,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,QAAQ,CAAC,wBAAwB,CAAC,EACjD,OAAO,CAAC,EAAE,OAAO,EACjB,iBAAiB,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAarC,SAAS,CAAC,uBAAuB,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,SAAS,GACrB,YAAY;IAIf;;OAEG;IACH,oBAAoB,CAClB,WAAW,EAAE,WAAW,EACxB,eAAe,CAAC,EAAE,eAAe,GAChC,aAAa,EAAE;IA8LlB;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CACvC,QAAQ,EAAE,WAAW,EACrB,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAC3B,kBAAkB,CAAC,EAAE,aAAa,EAAE,GACnC;QACD,SAAS,EAAE,KAAK,EAAE,CAAC;QACnB,QAAQ,EAAE,KAAK,EAAE,CAAC;KACnB;IAED;;OAEG;IACH,SAAS,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAoB7D;;;;;;;;OAQG;IACH,SAAS,CAAC,iBAAiB,CACzB,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,KAAK,EAAE,GACxB,WAAW;IAqCd;;;;;;;;;;OAUG;IACH,SAAS,CAAC,yBAAyB,CACjC,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,KAAK,EAAE,GACzB,WAAW;IAqCd;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,0BAA0B,CAClC,WAAW,EAAE,WAAW,EACxB,kBAAkB,EAAE,KAAK,EAAE,GAC1B,WAAW;IAyCd,SAAS,CAAC,YAAY,CACpB,MAAM,EAAE,aAAa,EAAE,EACvB,cAAc,EAAE,WAAW,GAC1B,aAAa,EAAE;CA8CnB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { toWei } from '@hyperlane-xyz/utils';
|
|
2
|
+
import { getBridgeConfig, } from '../utils/bridgeUtils.js';
|
|
1
3
|
/**
|
|
2
4
|
* Base abstract class for rebalancing strategies
|
|
3
5
|
*/
|
|
@@ -5,29 +7,48 @@ export class BaseStrategy {
|
|
|
5
7
|
chains;
|
|
6
8
|
metrics;
|
|
7
9
|
logger;
|
|
8
|
-
|
|
10
|
+
bridgeConfigs;
|
|
11
|
+
tokensByChainName;
|
|
12
|
+
constructor(chains, logger, bridgeConfigs, metrics, tokensByChainName) {
|
|
9
13
|
// Rebalancing makes sense only with more than one chain.
|
|
10
14
|
if (chains.length < 2) {
|
|
11
15
|
throw new Error('At least two chains must be configured');
|
|
12
16
|
}
|
|
13
17
|
this.chains = chains;
|
|
14
18
|
this.logger = logger;
|
|
19
|
+
this.bridgeConfigs = bridgeConfigs;
|
|
15
20
|
this.metrics = metrics;
|
|
21
|
+
this.tokensByChainName = tokensByChainName;
|
|
22
|
+
}
|
|
23
|
+
getBridgeConfigForRoute(origin, destination) {
|
|
24
|
+
return getBridgeConfig(this.bridgeConfigs, origin, destination);
|
|
16
25
|
}
|
|
17
26
|
/**
|
|
18
27
|
* Main method to get rebalancing routes
|
|
19
28
|
*/
|
|
20
|
-
getRebalancingRoutes(rawBalances) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}, 'Input rawBalances');
|
|
29
|
+
getRebalancingRoutes(rawBalances, inflightContext) {
|
|
30
|
+
const pendingRebalances = inflightContext?.pendingRebalances ?? [];
|
|
31
|
+
const pendingTransfers = inflightContext?.pendingTransfers ?? [];
|
|
32
|
+
const proposedRebalances = inflightContext?.proposedRebalances ?? [];
|
|
25
33
|
this.logger.info({
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
strategy: this.name,
|
|
35
|
+
balances: Object.entries(rawBalances).map(([c, b]) => ({
|
|
36
|
+
chain: c,
|
|
37
|
+
balance: b.toString(),
|
|
38
|
+
})),
|
|
39
|
+
pendingRebalances: pendingRebalances.length,
|
|
40
|
+
pendingTransfers: pendingTransfers.length,
|
|
41
|
+
proposedRebalances: proposedRebalances.length,
|
|
42
|
+
}, 'Strategy evaluating');
|
|
28
43
|
this.validateRawBalances(rawBalances);
|
|
44
|
+
// Store original balances for filtering step
|
|
45
|
+
const actualBalances = rawBalances;
|
|
46
|
+
// Step 1: Reserve collateral for pending user transfers
|
|
47
|
+
// This prevents draining collateral needed for incoming user transfers
|
|
48
|
+
const effectiveBalances = this.reserveCollateral(rawBalances, pendingTransfers);
|
|
29
49
|
// Get balances categorized by surplus and deficit
|
|
30
|
-
|
|
50
|
+
// Pass pending and proposed rebalances so strategy can account for them
|
|
51
|
+
const { surpluses, deficits } = this.getCategorizedBalances(effectiveBalances, pendingRebalances, proposedRebalances);
|
|
31
52
|
this.logger.debug({
|
|
32
53
|
context: this.constructor.name,
|
|
33
54
|
surpluses,
|
|
@@ -77,21 +98,27 @@ export class BaseStrategy {
|
|
|
77
98
|
const deficit = deficits[0];
|
|
78
99
|
// Transfers the whole surplus or just the amount to balance the deficit
|
|
79
100
|
const transferAmount = surplus.amount > deficit.amount ? deficit.amount : surplus.amount;
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
// Skip zero-amount routes (can occur after scaling when surpluses < deficits)
|
|
102
|
+
if (transferAmount > 0n) {
|
|
103
|
+
// Get bridge config for this route (with destination-specific overrides)
|
|
104
|
+
const bridgeConfig = this.getBridgeConfigForRoute(surplus.chain, deficit.chain);
|
|
105
|
+
// Creates the balancing route
|
|
106
|
+
routes.push({
|
|
107
|
+
origin: surplus.chain,
|
|
108
|
+
destination: deficit.chain,
|
|
109
|
+
amount: transferAmount,
|
|
110
|
+
bridge: bridgeConfig.bridge,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
86
113
|
// Decreases the amounts for the following iterations
|
|
87
114
|
deficit.amount -= transferAmount;
|
|
88
115
|
surplus.amount -= transferAmount;
|
|
89
|
-
// Removes the deficit if it is fully balanced
|
|
90
|
-
if (
|
|
116
|
+
// Removes the deficit if it is fully balanced (including scaled-to-zero)
|
|
117
|
+
if (deficit.amount <= 0n) {
|
|
91
118
|
deficits.shift();
|
|
92
119
|
}
|
|
93
120
|
// Removes the surplus if it has been drained
|
|
94
|
-
if (
|
|
121
|
+
if (surplus.amount <= 0n) {
|
|
95
122
|
surpluses.shift();
|
|
96
123
|
}
|
|
97
124
|
}
|
|
@@ -103,7 +130,17 @@ export class BaseStrategy {
|
|
|
103
130
|
context: this.constructor.name,
|
|
104
131
|
numberOfRoutes: routes.length,
|
|
105
132
|
}, 'Found rebalancing routes');
|
|
106
|
-
|
|
133
|
+
const filteredRoutes = this.filterRoutes(routes, actualBalances);
|
|
134
|
+
this.logger.debug({
|
|
135
|
+
context: this.constructor.name,
|
|
136
|
+
filteredRoutesCount: filteredRoutes.length,
|
|
137
|
+
droppedCount: routes.length - filteredRoutes.length,
|
|
138
|
+
}, 'Filtered rebalancing routes');
|
|
139
|
+
// Record metrics for each intent that passed filtering
|
|
140
|
+
for (const route of filteredRoutes) {
|
|
141
|
+
this.metrics?.recordIntentCreated(route, this.name);
|
|
142
|
+
}
|
|
143
|
+
return filteredRoutes;
|
|
107
144
|
}
|
|
108
145
|
/**
|
|
109
146
|
* Validates the raw balances against the chains configuration
|
|
@@ -123,5 +160,148 @@ export class BaseStrategy {
|
|
|
123
160
|
}
|
|
124
161
|
}
|
|
125
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Reserve collateral for pending user transfers.
|
|
165
|
+
* Subtracts pending transfer amounts from destination balances.
|
|
166
|
+
* This ensures we don't drain collateral needed for incoming transfers.
|
|
167
|
+
*
|
|
168
|
+
* @param rawBalances - Current on-chain balances
|
|
169
|
+
* @param pendingTransfers - Transfers that will need collateral on destination
|
|
170
|
+
* @returns Balances with reserved amounts subtracted
|
|
171
|
+
*/
|
|
172
|
+
reserveCollateral(rawBalances, pendingTransfers) {
|
|
173
|
+
if (pendingTransfers.length === 0) {
|
|
174
|
+
return rawBalances;
|
|
175
|
+
}
|
|
176
|
+
const reserved = { ...rawBalances };
|
|
177
|
+
for (const transfer of pendingTransfers) {
|
|
178
|
+
const destBalance = reserved[transfer.destination] ?? 0n;
|
|
179
|
+
// Reserve the transfer amount from destination
|
|
180
|
+
// Allow negative values to indicate collateral deficits
|
|
181
|
+
reserved[transfer.destination] = destBalance - transfer.amount;
|
|
182
|
+
this.logger.debug({
|
|
183
|
+
context: this.constructor.name,
|
|
184
|
+
destination: transfer.destination,
|
|
185
|
+
amount: transfer.amount.toString(),
|
|
186
|
+
newBalance: reserved[transfer.destination].toString(),
|
|
187
|
+
}, 'Reserved collateral for pending transfer');
|
|
188
|
+
}
|
|
189
|
+
this.logger.info({
|
|
190
|
+
reservations: pendingTransfers.map((t) => ({
|
|
191
|
+
destination: t.destination,
|
|
192
|
+
amount: t.amount.toString(),
|
|
193
|
+
})),
|
|
194
|
+
}, 'Collateral reserved for pending transfers');
|
|
195
|
+
return reserved;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Simulate pending rebalances by adding to destination balances.
|
|
199
|
+
*
|
|
200
|
+
* Only adds to destination - does NOT subtract from origin because:
|
|
201
|
+
* - pendingRebalances only contains in_progress intents (origin tx confirmed)
|
|
202
|
+
* - Origin balance is already deducted on-chain
|
|
203
|
+
*
|
|
204
|
+
* @param rawBalances - Current balances (may already have collateral reserved)
|
|
205
|
+
* @param pendingRebalances - In-flight rebalance operations (in_progress only)
|
|
206
|
+
* @returns Simulated future balances after rebalances complete
|
|
207
|
+
*/
|
|
208
|
+
simulatePendingRebalances(rawBalances, pendingRebalances) {
|
|
209
|
+
if (pendingRebalances.length === 0) {
|
|
210
|
+
return rawBalances;
|
|
211
|
+
}
|
|
212
|
+
const simulated = { ...rawBalances };
|
|
213
|
+
for (const rebalance of pendingRebalances) {
|
|
214
|
+
// Only add to destination - origin is already deducted on-chain
|
|
215
|
+
// (pendingRebalances only contains in_progress intents with confirmed origin tx)
|
|
216
|
+
simulated[rebalance.destination] =
|
|
217
|
+
(simulated[rebalance.destination] ?? 0n) + rebalance.amount;
|
|
218
|
+
this.logger.debug({
|
|
219
|
+
context: this.constructor.name,
|
|
220
|
+
destination: rebalance.destination,
|
|
221
|
+
amount: rebalance.amount.toString(),
|
|
222
|
+
}, 'Simulated pending rebalance (destination increase)');
|
|
223
|
+
}
|
|
224
|
+
this.logger.info({
|
|
225
|
+
simulations: pendingRebalances.map((r) => ({
|
|
226
|
+
from: r.origin,
|
|
227
|
+
to: r.destination,
|
|
228
|
+
amount: r.amount.toString(),
|
|
229
|
+
})),
|
|
230
|
+
}, 'Simulated pending rebalances');
|
|
231
|
+
return simulated;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Simulate proposed rebalances by subtracting from origin AND adding to destination.
|
|
235
|
+
*
|
|
236
|
+
* Unlike pendingRebalances, proposedRebalances are routes from earlier strategies
|
|
237
|
+
* in the same cycle that haven't been executed yet. Therefore:
|
|
238
|
+
* - Origin balance has NOT been deducted on-chain
|
|
239
|
+
* - We must simulate both sides to maintain accurate total balance
|
|
240
|
+
*
|
|
241
|
+
* @param rawBalances - Current balances (may already have pending rebalances simulated)
|
|
242
|
+
* @param proposedRebalances - Routes from earlier strategies (not yet executed)
|
|
243
|
+
* @returns Simulated balances after proposed rebalances complete
|
|
244
|
+
*/
|
|
245
|
+
simulateProposedRebalances(rawBalances, proposedRebalances) {
|
|
246
|
+
if (proposedRebalances.length === 0) {
|
|
247
|
+
return rawBalances;
|
|
248
|
+
}
|
|
249
|
+
const simulated = { ...rawBalances };
|
|
250
|
+
for (const rebalance of proposedRebalances) {
|
|
251
|
+
// Subtract from origin (not yet deducted on-chain)
|
|
252
|
+
simulated[rebalance.origin] =
|
|
253
|
+
(simulated[rebalance.origin] ?? 0n) - rebalance.amount;
|
|
254
|
+
// Add to destination
|
|
255
|
+
simulated[rebalance.destination] =
|
|
256
|
+
(simulated[rebalance.destination] ?? 0n) + rebalance.amount;
|
|
257
|
+
this.logger.debug({
|
|
258
|
+
context: this.constructor.name,
|
|
259
|
+
origin: rebalance.origin,
|
|
260
|
+
destination: rebalance.destination,
|
|
261
|
+
amount: rebalance.amount.toString(),
|
|
262
|
+
}, 'Simulated proposed rebalance (origin decrease, destination increase)');
|
|
263
|
+
}
|
|
264
|
+
this.logger.info({
|
|
265
|
+
simulations: proposedRebalances.map((r) => ({
|
|
266
|
+
from: r.origin,
|
|
267
|
+
to: r.destination,
|
|
268
|
+
amount: r.amount.toString(),
|
|
269
|
+
})),
|
|
270
|
+
}, 'Simulated proposed rebalances');
|
|
271
|
+
return simulated;
|
|
272
|
+
}
|
|
273
|
+
filterRoutes(routes, actualBalances) {
|
|
274
|
+
return routes.filter((route) => {
|
|
275
|
+
const balance = actualBalances[route.origin] ?? 0n;
|
|
276
|
+
if (balance < route.amount) {
|
|
277
|
+
this.logger.warn({
|
|
278
|
+
context: this.constructor.name,
|
|
279
|
+
origin: route.origin,
|
|
280
|
+
destination: route.destination,
|
|
281
|
+
required: route.amount.toString(),
|
|
282
|
+
available: balance.toString(),
|
|
283
|
+
}, 'Dropping route due to insufficient balance');
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
if (this.tokensByChainName) {
|
|
287
|
+
const token = this.tokensByChainName[route.origin];
|
|
288
|
+
if (token) {
|
|
289
|
+
const bridgeConfig = this.getBridgeConfigForRoute(route.origin, route.destination);
|
|
290
|
+
const minAmount = BigInt(toWei(bridgeConfig.bridgeMinAcceptedAmount, token.decimals));
|
|
291
|
+
if (route.amount < minAmount) {
|
|
292
|
+
this.logger.info({
|
|
293
|
+
context: this.constructor.name,
|
|
294
|
+
origin: route.origin,
|
|
295
|
+
destination: route.destination,
|
|
296
|
+
amount: route.amount.toString(),
|
|
297
|
+
minAmount: minAmount.toString(),
|
|
298
|
+
}, 'Dropping route below bridgeMinAcceptedAmount');
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
126
306
|
}
|
|
127
307
|
//# sourceMappingURL=BaseStrategy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStrategy.js","sourceRoot":"","sources":["../../src/strategy/BaseStrategy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseStrategy.js","sourceRoot":"","sources":["../../src/strategy/BaseStrategy.ts"],"names":[],"mappings":"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"}
|