@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
package/src/metrics/Metrics.ts
CHANGED
|
@@ -22,13 +22,15 @@ import { ProtocolType, tryFn } from '@hyperlane-xyz/utils';
|
|
|
22
22
|
|
|
23
23
|
import { type IMetrics } from '../interfaces/IMetrics.js';
|
|
24
24
|
import { type MonitorEvent } from '../interfaces/IMonitor.js';
|
|
25
|
-
import { type
|
|
25
|
+
import { type StrategyRoute } from '../interfaces/IStrategy.js';
|
|
26
26
|
|
|
27
27
|
import { type PriceGetter } from './PriceGetter.js';
|
|
28
28
|
import {
|
|
29
29
|
metricsRegister,
|
|
30
|
+
rebalancerActionsCreatedTotal,
|
|
30
31
|
rebalancerExecutionAmount,
|
|
31
32
|
rebalancerExecutionTotal,
|
|
33
|
+
rebalancerIntentsCreatedTotal,
|
|
32
34
|
rebalancerPollingErrorsTotal,
|
|
33
35
|
updateManagedLockboxBalanceMetrics,
|
|
34
36
|
updateNativeWalletBalanceMetrics,
|
|
@@ -64,10 +66,7 @@ export class Metrics implements IMetrics {
|
|
|
64
66
|
.inc();
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
recordRebalanceAmount(
|
|
68
|
-
route: RebalancingRoute,
|
|
69
|
-
originTokenAmount: TokenAmount,
|
|
70
|
-
) {
|
|
69
|
+
recordRebalanceAmount(route: StrategyRoute, originTokenAmount: TokenAmount) {
|
|
71
70
|
rebalancerExecutionAmount
|
|
72
71
|
.labels({
|
|
73
72
|
warp_route_id: this.warpRouteId,
|
|
@@ -90,6 +89,28 @@ export class Metrics implements IMetrics {
|
|
|
90
89
|
.inc();
|
|
91
90
|
}
|
|
92
91
|
|
|
92
|
+
recordIntentCreated(route: StrategyRoute, strategy: string) {
|
|
93
|
+
rebalancerIntentsCreatedTotal
|
|
94
|
+
.labels({
|
|
95
|
+
warp_route_id: this.warpRouteId,
|
|
96
|
+
strategy,
|
|
97
|
+
origin: route.origin,
|
|
98
|
+
destination: route.destination,
|
|
99
|
+
})
|
|
100
|
+
.inc();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
recordActionAttempt(route: StrategyRoute, succeeded: boolean) {
|
|
104
|
+
rebalancerActionsCreatedTotal
|
|
105
|
+
.labels({
|
|
106
|
+
warp_route_id: this.warpRouteId,
|
|
107
|
+
origin: route.origin,
|
|
108
|
+
destination: route.destination,
|
|
109
|
+
succeeded: String(succeeded),
|
|
110
|
+
})
|
|
111
|
+
.inc();
|
|
112
|
+
}
|
|
113
|
+
|
|
93
114
|
async processToken({
|
|
94
115
|
token,
|
|
95
116
|
bridgedSupply,
|
|
@@ -42,6 +42,20 @@ export const rebalancerPollingErrorsTotal = new Counter({
|
|
|
42
42
|
labelNames: ['warp_route_id'],
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
+
export const rebalancerIntentsCreatedTotal = new Counter({
|
|
46
|
+
name: 'hyperlane_rebalancer_intents_created_total',
|
|
47
|
+
help: 'Total number of rebalancing intents (routes) created.',
|
|
48
|
+
registers: [metricsRegister],
|
|
49
|
+
labelNames: ['warp_route_id', 'strategy', 'origin', 'destination'],
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const rebalancerActionsCreatedTotal = new Counter({
|
|
53
|
+
name: 'hyperlane_rebalancer_actions_created_total',
|
|
54
|
+
help: 'Total number of rebalancing actions (transactions) attempted.',
|
|
55
|
+
registers: [metricsRegister],
|
|
56
|
+
labelNames: ['warp_route_id', 'origin', 'destination', 'succeeded'],
|
|
57
|
+
});
|
|
58
|
+
|
|
45
59
|
/**
|
|
46
60
|
* Updates token balance metrics for a warp route token.
|
|
47
61
|
*/
|
package/src/monitor/Monitor.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
2
1
|
import { type Logger } from 'pino';
|
|
3
2
|
|
|
4
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
EthJsonRpcBlockParameterTag,
|
|
5
|
+
type Token,
|
|
6
|
+
type WarpCore,
|
|
7
|
+
} from '@hyperlane-xyz/sdk';
|
|
5
8
|
import { sleep } from '@hyperlane-xyz/utils';
|
|
6
9
|
|
|
7
10
|
import {
|
|
11
|
+
type ConfirmedBlockTag,
|
|
12
|
+
type ConfirmedBlockTags,
|
|
8
13
|
type IMonitor,
|
|
9
14
|
type MonitorEvent,
|
|
10
15
|
MonitorEventType,
|
|
@@ -14,9 +19,12 @@ import {
|
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Simple monitor implementation that polls warp route collateral balances and emits them as MonitorEvent.
|
|
22
|
+
* Awaits the TokenInfo handler before starting the next cycle to prevent race conditions.
|
|
17
23
|
*/
|
|
18
24
|
export class Monitor implements IMonitor {
|
|
19
|
-
private
|
|
25
|
+
private tokenInfoHandler?: (event: MonitorEvent) => void | Promise<void>;
|
|
26
|
+
private errorHandler?: (event: Error) => void;
|
|
27
|
+
private startHandler?: () => void;
|
|
20
28
|
private isMonitorRunning = false;
|
|
21
29
|
private resolveStop: (() => void) | null = null;
|
|
22
30
|
private stopPromise: Promise<void> | null = null;
|
|
@@ -30,25 +38,69 @@ export class Monitor implements IMonitor {
|
|
|
30
38
|
private readonly logger: Logger,
|
|
31
39
|
) {}
|
|
32
40
|
|
|
41
|
+
private async getConfirmedBlockTag(
|
|
42
|
+
chainName: string,
|
|
43
|
+
): Promise<ConfirmedBlockTag> {
|
|
44
|
+
try {
|
|
45
|
+
const metadata = this.warpCore.multiProvider.getChainMetadata(chainName);
|
|
46
|
+
const reorgPeriod = metadata.blocks?.reorgPeriod ?? 32;
|
|
47
|
+
|
|
48
|
+
if (typeof reorgPeriod === 'string') {
|
|
49
|
+
return reorgPeriod as EthJsonRpcBlockParameterTag;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const provider =
|
|
53
|
+
this.warpCore.multiProvider.getEthersV5Provider(chainName);
|
|
54
|
+
const latestBlock = await provider.getBlockNumber();
|
|
55
|
+
return Math.max(0, latestBlock - reorgPeriod);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
this.logger.warn(
|
|
58
|
+
{ chain: chainName, error: (error as Error).message },
|
|
59
|
+
'Failed to get confirmed block, using latest',
|
|
60
|
+
);
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private async computeConfirmedBlockTags(): Promise<ConfirmedBlockTags> {
|
|
66
|
+
const blockTags: ConfirmedBlockTags = {};
|
|
67
|
+
const chains = new Set(this.warpCore.tokens.map((t) => t.chainName));
|
|
68
|
+
|
|
69
|
+
for (const chain of chains) {
|
|
70
|
+
blockTags[chain] = await this.getConfirmedBlockTag(chain);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return blockTags;
|
|
74
|
+
}
|
|
75
|
+
|
|
33
76
|
// overloads from IMonitor
|
|
34
77
|
on(
|
|
35
78
|
eventName: MonitorEventType.TokenInfo,
|
|
36
|
-
fn: (event: MonitorEvent) => void
|
|
79
|
+
fn: (event: MonitorEvent) => void | Promise<void>,
|
|
37
80
|
): this;
|
|
38
81
|
on(eventName: MonitorEventType.Error, fn: (event: Error) => void): this;
|
|
39
82
|
on(eventName: MonitorEventType.Start, fn: () => void): this;
|
|
40
|
-
on(eventName: string, fn: (...args: any[]) => void): this {
|
|
41
|
-
|
|
83
|
+
on(eventName: string, fn: (...args: any[]) => void | Promise<void>): this {
|
|
84
|
+
switch (eventName) {
|
|
85
|
+
case MonitorEventType.TokenInfo:
|
|
86
|
+
this.tokenInfoHandler = fn as (
|
|
87
|
+
event: MonitorEvent,
|
|
88
|
+
) => void | Promise<void>;
|
|
89
|
+
break;
|
|
90
|
+
case MonitorEventType.Error:
|
|
91
|
+
this.errorHandler = fn as (event: Error) => void;
|
|
92
|
+
break;
|
|
93
|
+
case MonitorEventType.Start:
|
|
94
|
+
this.startHandler = fn as () => void;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
42
97
|
return this;
|
|
43
98
|
}
|
|
44
99
|
|
|
45
100
|
async start() {
|
|
46
101
|
if (this.isMonitorRunning) {
|
|
47
102
|
// Cannot start the same monitor multiple times
|
|
48
|
-
this.
|
|
49
|
-
MonitorEventType.Error,
|
|
50
|
-
new MonitorStartError('Monitor already running'),
|
|
51
|
-
);
|
|
103
|
+
this.errorHandler?.(new MonitorStartError('Monitor already running'));
|
|
52
104
|
return;
|
|
53
105
|
}
|
|
54
106
|
|
|
@@ -58,13 +110,19 @@ export class Monitor implements IMonitor {
|
|
|
58
110
|
{ checkFrequency: this.checkFrequency },
|
|
59
111
|
'Monitor started',
|
|
60
112
|
);
|
|
61
|
-
this.
|
|
113
|
+
this.startHandler?.();
|
|
62
114
|
|
|
63
115
|
while (this.isMonitorRunning) {
|
|
116
|
+
const cycleStart = Date.now();
|
|
117
|
+
|
|
64
118
|
try {
|
|
65
119
|
this.logger.debug('Polling cycle started');
|
|
120
|
+
|
|
121
|
+
const confirmedBlockTags = await this.computeConfirmedBlockTags();
|
|
122
|
+
|
|
66
123
|
const event: MonitorEvent = {
|
|
67
124
|
tokensInfo: [],
|
|
125
|
+
confirmedBlockTags,
|
|
68
126
|
};
|
|
69
127
|
|
|
70
128
|
for (const token of this.warpCore.tokens) {
|
|
@@ -76,7 +134,11 @@ export class Monitor implements IMonitor {
|
|
|
76
134
|
},
|
|
77
135
|
'Checking token',
|
|
78
136
|
);
|
|
79
|
-
const
|
|
137
|
+
const blockTag = confirmedBlockTags[token.chainName];
|
|
138
|
+
const bridgedSupply = await this.getTokenBridgedSupply(
|
|
139
|
+
token,
|
|
140
|
+
blockTag,
|
|
141
|
+
);
|
|
80
142
|
|
|
81
143
|
event.tokensInfo.push({
|
|
82
144
|
token,
|
|
@@ -84,12 +146,12 @@ export class Monitor implements IMonitor {
|
|
|
84
146
|
});
|
|
85
147
|
}
|
|
86
148
|
|
|
87
|
-
|
|
88
|
-
|
|
149
|
+
if (this.tokenInfoHandler) {
|
|
150
|
+
await this.tokenInfoHandler(event);
|
|
151
|
+
}
|
|
89
152
|
this.logger.debug('Polling cycle completed');
|
|
90
153
|
} catch (error) {
|
|
91
|
-
this.
|
|
92
|
-
MonitorEventType.Error,
|
|
154
|
+
this.errorHandler?.(
|
|
93
155
|
new MonitorPollingError(
|
|
94
156
|
`Error during monitor execution cycle: ${(error as Error).message}`,
|
|
95
157
|
error as Error,
|
|
@@ -97,12 +159,16 @@ export class Monitor implements IMonitor {
|
|
|
97
159
|
);
|
|
98
160
|
}
|
|
99
161
|
|
|
100
|
-
//
|
|
101
|
-
|
|
162
|
+
// Smart sleep: only wait for remaining time after cycle completes
|
|
163
|
+
const elapsed = Date.now() - cycleStart;
|
|
164
|
+
const remaining = this.checkFrequency - elapsed;
|
|
165
|
+
if (remaining > 0) {
|
|
166
|
+
await sleep(remaining);
|
|
167
|
+
}
|
|
168
|
+
// If elapsed >= checkFrequency, start next cycle immediately
|
|
102
169
|
}
|
|
103
170
|
} catch (error) {
|
|
104
|
-
this.
|
|
105
|
-
MonitorEventType.Error,
|
|
171
|
+
this.errorHandler?.(
|
|
106
172
|
new MonitorStartError(
|
|
107
173
|
`Error starting monitor: ${(error as Error).message}`,
|
|
108
174
|
error as Error,
|
|
@@ -111,7 +177,9 @@ export class Monitor implements IMonitor {
|
|
|
111
177
|
}
|
|
112
178
|
|
|
113
179
|
// After the loop has been gracefully terminated, we can clean up.
|
|
114
|
-
this.
|
|
180
|
+
this.tokenInfoHandler = undefined;
|
|
181
|
+
this.errorHandler = undefined;
|
|
182
|
+
this.startHandler = undefined;
|
|
115
183
|
this.logger.info('Monitor stopped');
|
|
116
184
|
|
|
117
185
|
// If stop() was called, resolve the promise to signal that we're done.
|
|
@@ -124,6 +192,7 @@ export class Monitor implements IMonitor {
|
|
|
124
192
|
|
|
125
193
|
private async getTokenBridgedSupply(
|
|
126
194
|
token: Token,
|
|
195
|
+
blockTag?: ConfirmedBlockTag,
|
|
127
196
|
): Promise<bigint | undefined> {
|
|
128
197
|
if (!token.isHypToken()) {
|
|
129
198
|
this.logger.warn(
|
|
@@ -138,7 +207,25 @@ export class Monitor implements IMonitor {
|
|
|
138
207
|
}
|
|
139
208
|
|
|
140
209
|
const adapter = token.getHypAdapter(this.warpCore.multiProvider);
|
|
141
|
-
|
|
210
|
+
let bridgedSupply: bigint | undefined;
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
bridgedSupply = await adapter.getBridgedSupply({ blockTag });
|
|
214
|
+
this.logger.debug(
|
|
215
|
+
{ chain: token.chainName, blockTag },
|
|
216
|
+
'Queried confirmed balance',
|
|
217
|
+
);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
this.logger.warn(
|
|
220
|
+
{
|
|
221
|
+
chain: token.chainName,
|
|
222
|
+
blockTag,
|
|
223
|
+
error: (error as Error).message,
|
|
224
|
+
},
|
|
225
|
+
'Historical block query failed, falling back to latest',
|
|
226
|
+
);
|
|
227
|
+
bridgedSupply = await adapter.getBridgedSupply();
|
|
228
|
+
}
|
|
142
229
|
|
|
143
230
|
if (bridgedSupply === undefined) {
|
|
144
231
|
this.logger.warn(
|