@hyperlane-xyz/rebalancer 2.0.0 → 3.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/dist/bridges/LiFiBridge.d.ts +67 -0
- package/dist/bridges/LiFiBridge.d.ts.map +1 -0
- package/dist/bridges/LiFiBridge.js +386 -0
- package/dist/bridges/LiFiBridge.js.map +1 -0
- package/dist/config/RebalancerConfig.d.ts +7 -2
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +7 -4
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +134 -1
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +1016 -304
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +105 -10
- package/dist/config/types.js.map +1 -1
- package/dist/core/InventoryRebalancer.d.ts +190 -0
- package/dist/core/InventoryRebalancer.d.ts.map +1 -0
- package/dist/core/InventoryRebalancer.js +885 -0
- package/dist/core/InventoryRebalancer.js.map +1 -0
- package/dist/core/InventoryRebalancer.test.d.ts +2 -0
- package/dist/core/InventoryRebalancer.test.d.ts.map +1 -0
- package/dist/core/InventoryRebalancer.test.js +1351 -0
- package/dist/core/InventoryRebalancer.test.js.map +1 -0
- package/dist/core/Rebalancer.d.ts +11 -4
- package/dist/core/Rebalancer.d.ts.map +1 -1
- package/dist/core/Rebalancer.js +92 -9
- package/dist/core/Rebalancer.js.map +1 -1
- package/dist/core/Rebalancer.test.js +82 -49
- package/dist/core/Rebalancer.test.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.d.ts +30 -9
- package/dist/core/RebalancerOrchestrator.d.ts.map +1 -1
- package/dist/core/RebalancerOrchestrator.js +79 -71
- package/dist/core/RebalancerOrchestrator.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.test.d.ts +2 -0
- package/dist/core/RebalancerOrchestrator.test.d.ts.map +1 -0
- package/dist/core/RebalancerOrchestrator.test.js +714 -0
- package/dist/core/RebalancerOrchestrator.test.js.map +1 -0
- package/dist/core/RebalancerService.d.ts +7 -3
- package/dist/core/RebalancerService.d.ts.map +1 -1
- package/dist/core/RebalancerService.js +44 -24
- package/dist/core/RebalancerService.js.map +1 -1
- package/dist/core/RebalancerService.test.js +71 -109
- package/dist/core/RebalancerService.test.js.map +1 -1
- package/dist/e2e/collateral-deficit.e2e-test.js +1 -3
- package/dist/e2e/collateral-deficit.e2e-test.js.map +1 -1
- package/dist/e2e/composite.e2e-test.js.map +1 -1
- package/dist/e2e/harness/BridgeSetup.d.ts +6 -0
- package/dist/e2e/harness/BridgeSetup.d.ts.map +1 -1
- package/dist/e2e/harness/BridgeSetup.js +10 -1
- package/dist/e2e/harness/BridgeSetup.js.map +1 -1
- package/dist/e2e/harness/TestHelpers.d.ts.map +1 -1
- package/dist/e2e/harness/TestHelpers.js +1 -4
- package/dist/e2e/harness/TestHelpers.js.map +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -1
- package/dist/e2e/harness/TestRebalancer.js +6 -7
- package/dist/e2e/harness/TestRebalancer.js.map +1 -1
- package/dist/e2e/minAmount.e2e-test.js +0 -1
- package/dist/e2e/minAmount.e2e-test.js.map +1 -1
- package/dist/e2e/weighted.e2e-test.js +0 -1
- package/dist/e2e/weighted.e2e-test.js.map +1 -1
- package/dist/factories/RebalancerContextFactory.d.ts +48 -6
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
- package/dist/factories/RebalancerContextFactory.js +170 -17
- package/dist/factories/RebalancerContextFactory.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IExternalBridge.d.ts +101 -0
- package/dist/interfaces/IExternalBridge.d.ts.map +1 -0
- package/dist/interfaces/IExternalBridge.js +2 -0
- package/dist/interfaces/IExternalBridge.js.map +1 -0
- package/dist/interfaces/IMonitor.d.ts +1 -0
- package/dist/interfaces/IMonitor.d.ts.map +1 -1
- package/dist/interfaces/IRebalancer.d.ts +25 -25
- package/dist/interfaces/IRebalancer.d.ts.map +1 -1
- package/dist/interfaces/IStrategy.d.ts +36 -3
- package/dist/interfaces/IStrategy.d.ts.map +1 -1
- package/dist/interfaces/IStrategy.js +12 -1
- package/dist/interfaces/IStrategy.js.map +1 -1
- package/dist/metrics/PriceGetter.js +1 -1
- package/dist/metrics/PriceGetter.js.map +1 -1
- package/dist/metrics/scripts/metrics.d.ts +3 -3
- package/dist/monitor/Monitor.d.ts +12 -2
- package/dist/monitor/Monitor.d.ts.map +1 -1
- package/dist/monitor/Monitor.js +46 -1
- package/dist/monitor/Monitor.js.map +1 -1
- package/dist/service.js +40 -17
- package/dist/service.js.map +1 -1
- package/dist/strategy/BaseStrategy.d.ts +12 -6
- package/dist/strategy/BaseStrategy.d.ts.map +1 -1
- package/dist/strategy/BaseStrategy.js +56 -21
- package/dist/strategy/BaseStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.js +19 -11
- package/dist/strategy/CollateralDeficitStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.test.js +135 -2
- package/dist/strategy/CollateralDeficitStrategy.test.js.map +1 -1
- package/dist/strategy/CompositeStrategy.test.js +13 -0
- package/dist/strategy/CompositeStrategy.test.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.test.js +4 -0
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
- package/dist/strategy/StrategyFactory.d.ts +2 -1
- package/dist/strategy/StrategyFactory.d.ts.map +1 -1
- package/dist/strategy/StrategyFactory.js +24 -8
- package/dist/strategy/StrategyFactory.js.map +1 -1
- package/dist/strategy/WeightedStrategy.test.js +6 -0
- package/dist/strategy/WeightedStrategy.test.js.map +1 -1
- package/dist/test/helpers.d.ts +8 -7
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +23 -5
- package/dist/test/helpers.js.map +1 -1
- package/dist/test/lifiMocks.d.ts +51 -0
- package/dist/test/lifiMocks.d.ts.map +1 -0
- package/dist/test/lifiMocks.js +130 -0
- package/dist/test/lifiMocks.js.map +1 -0
- package/dist/tracking/ActionTracker.d.ts +33 -1
- package/dist/tracking/ActionTracker.d.ts.map +1 -1
- package/dist/tracking/ActionTracker.js +193 -22
- package/dist/tracking/ActionTracker.js.map +1 -1
- package/dist/tracking/ActionTracker.test.js +107 -19
- package/dist/tracking/ActionTracker.test.js.map +1 -1
- package/dist/tracking/IActionTracker.d.ts +47 -3
- package/dist/tracking/IActionTracker.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.js +24 -7
- package/dist/tracking/InflightContextAdapter.js.map +1 -1
- package/dist/tracking/InflightContextAdapter.test.js +7 -4
- package/dist/tracking/InflightContextAdapter.test.js.map +1 -1
- package/dist/tracking/types.d.ts +31 -2
- package/dist/tracking/types.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.d.ts +2 -1
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +13 -8
- package/dist/utils/ExplorerClient.js.map +1 -1
- package/dist/utils/bridgeUtils.d.ts +27 -4
- package/dist/utils/bridgeUtils.d.ts.map +1 -1
- package/dist/utils/bridgeUtils.js +38 -0
- package/dist/utils/bridgeUtils.js.map +1 -1
- package/dist/utils/bridgeUtils.test.js +9 -0
- package/dist/utils/bridgeUtils.test.js.map +1 -1
- package/dist/utils/gasEstimation.d.ts +65 -0
- package/dist/utils/gasEstimation.d.ts.map +1 -0
- package/dist/utils/gasEstimation.js +176 -0
- package/dist/utils/gasEstimation.js.map +1 -0
- package/dist/utils/tokenUtils.d.ts +9 -1
- package/dist/utils/tokenUtils.d.ts.map +1 -1
- package/dist/utils/tokenUtils.js +11 -0
- package/dist/utils/tokenUtils.js.map +1 -1
- package/package.json +9 -7
- package/src/bridges/LiFiBridge.ts +538 -0
- package/src/config/RebalancerConfig.test.ts +160 -0
- package/src/config/RebalancerConfig.ts +14 -3
- package/src/config/types.ts +136 -10
- package/src/core/InventoryRebalancer.test.ts +1684 -0
- package/src/core/InventoryRebalancer.ts +1255 -0
- package/src/core/Rebalancer.test.ts +84 -30
- package/src/core/Rebalancer.ts +144 -23
- package/src/core/RebalancerOrchestrator.test.ts +860 -0
- package/src/core/RebalancerOrchestrator.ts +146 -95
- package/src/core/RebalancerService.test.ts +80 -123
- package/src/core/RebalancerService.ts +67 -33
- package/src/e2e/collateral-deficit.e2e-test.ts +2 -4
- package/src/e2e/composite.e2e-test.ts +5 -5
- package/src/e2e/harness/BridgeSetup.ts +28 -1
- package/src/e2e/harness/TestHelpers.ts +1 -4
- package/src/e2e/harness/TestRebalancer.ts +7 -7
- package/src/e2e/minAmount.e2e-test.ts +1 -2
- package/src/e2e/weighted.e2e-test.ts +1 -2
- package/src/factories/RebalancerContextFactory.ts +293 -24
- package/src/index.ts +20 -5
- package/src/interfaces/IExternalBridge.ts +115 -0
- package/src/interfaces/IMonitor.ts +1 -0
- package/src/interfaces/IRebalancer.ts +45 -29
- package/src/interfaces/IStrategy.ts +50 -3
- package/src/metrics/PriceGetter.ts +1 -1
- package/src/monitor/Monitor.ts +81 -2
- package/src/service.ts +59 -18
- package/src/strategy/BaseStrategy.ts +77 -24
- package/src/strategy/CollateralDeficitStrategy.test.ts +181 -4
- package/src/strategy/CollateralDeficitStrategy.ts +42 -15
- package/src/strategy/CompositeStrategy.test.ts +13 -0
- package/src/strategy/MinAmountStrategy.test.ts +4 -0
- package/src/strategy/StrategyFactory.ts +33 -6
- package/src/strategy/WeightedStrategy.test.ts +6 -0
- package/src/test/helpers.ts +39 -14
- package/src/test/lifiMocks.ts +174 -0
- package/src/tracking/ActionTracker.test.ts +122 -19
- package/src/tracking/ActionTracker.ts +284 -24
- package/src/tracking/IActionTracker.ts +58 -3
- package/src/tracking/InflightContextAdapter.test.ts +7 -4
- package/src/tracking/InflightContextAdapter.ts +42 -9
- package/src/tracking/types.ts +43 -2
- package/src/utils/ExplorerClient.ts +23 -10
- package/src/utils/bridgeUtils.test.ts +9 -0
- package/src/utils/bridgeUtils.ts +75 -6
- package/src/utils/gasEstimation.ts +272 -0
- package/src/utils/tokenUtils.ts +12 -0
- package/dist/tracking/index.d.ts +0 -7
- package/dist/tracking/index.d.ts.map +0 -1
- package/dist/tracking/index.js +0 -6
- package/dist/tracking/index.js.map +0 -1
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -5
- package/dist/utils/index.js.map +0 -1
- package/src/tracking/index.ts +0 -36
- package/src/utils/index.ts +0 -4
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { BigNumber, ethers, providers } from 'ethers';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ERC20__factory,
|
|
5
|
+
MovableCollateralRouter__factory,
|
|
6
|
+
} from '@hyperlane-xyz/core';
|
|
4
7
|
|
|
5
8
|
export async function setupCollateralBalances(
|
|
6
9
|
providers: Map<string, providers.JsonRpcProvider>,
|
|
@@ -65,3 +68,27 @@ export async function getAllCollateralBalances(
|
|
|
65
68
|
}
|
|
66
69
|
return balances;
|
|
67
70
|
}
|
|
71
|
+
|
|
72
|
+
export interface AllowedBridgeConfig {
|
|
73
|
+
monitoredRouterAddress: string;
|
|
74
|
+
bridgeAddress: string;
|
|
75
|
+
destinationDomain: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function configureAllowedBridges(
|
|
79
|
+
provider: providers.JsonRpcProvider,
|
|
80
|
+
configs: AllowedBridgeConfig[],
|
|
81
|
+
deployerKey: string,
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
if (configs.length === 0) return;
|
|
84
|
+
|
|
85
|
+
const deployer = new ethers.Wallet(deployerKey, provider);
|
|
86
|
+
const router = MovableCollateralRouter__factory.connect(
|
|
87
|
+
configs[0].monitoredRouterAddress,
|
|
88
|
+
deployer,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
for (const config of configs) {
|
|
92
|
+
await router.addBridge(config.destinationDomain, config.bridgeAddress);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -21,7 +21,7 @@ import { RebalancerContextFactory } from '../../factories/RebalancerContextFacto
|
|
|
21
21
|
import type { ConfirmedBlockTags } from '../../interfaces/IMonitor.js';
|
|
22
22
|
import type { IStrategy } from '../../interfaces/IStrategy.js';
|
|
23
23
|
import type { Monitor } from '../../monitor/Monitor.js';
|
|
24
|
-
import type { IActionTracker } from '../../tracking/
|
|
24
|
+
import type { IActionTracker } from '../../tracking/IActionTracker.js';
|
|
25
25
|
import type { ExplorerMessage } from '../../utils/ExplorerClient.js';
|
|
26
26
|
import {
|
|
27
27
|
ANVIL_TEST_PRIVATE_KEY,
|
|
@@ -212,6 +212,7 @@ export class TestRebalancerBuilder {
|
|
|
212
212
|
const contextFactory = await RebalancerContextFactory.create(
|
|
213
213
|
rebalancerConfig,
|
|
214
214
|
workingMultiProvider,
|
|
215
|
+
undefined,
|
|
215
216
|
mpp,
|
|
216
217
|
registry,
|
|
217
218
|
this.logger,
|
|
@@ -225,18 +226,17 @@ export class TestRebalancerBuilder {
|
|
|
225
226
|
await tracker.initialize();
|
|
226
227
|
this.logger.info('ActionTracker initialized with mock explorer');
|
|
227
228
|
|
|
228
|
-
// In execute mode, create
|
|
229
|
-
const
|
|
229
|
+
// In execute mode, create actual Rebalancers to enable intent creation and execution
|
|
230
|
+
const rebalancers =
|
|
230
231
|
this.executionMode === 'execute'
|
|
231
|
-
? contextFactory.
|
|
232
|
-
:
|
|
232
|
+
? (await contextFactory.createRebalancers(tracker)).rebalancers
|
|
233
|
+
: [];
|
|
233
234
|
|
|
234
235
|
const orchestratorDeps: RebalancerOrchestratorDeps = {
|
|
235
236
|
strategy,
|
|
236
|
-
|
|
237
|
+
rebalancers,
|
|
237
238
|
actionTracker: tracker,
|
|
238
239
|
inflightContextAdapter: adapter,
|
|
239
|
-
multiProvider: workingMultiProvider,
|
|
240
240
|
rebalancerConfig,
|
|
241
241
|
logger: this.logger,
|
|
242
242
|
};
|
|
@@ -212,7 +212,7 @@ describe('MinAmountStrategy E2E', function () {
|
|
|
212
212
|
hyperlaneCore,
|
|
213
213
|
{
|
|
214
214
|
dispatchTx: rebalanceTxReceipt,
|
|
215
|
-
messageId: actionToArbitrum.messageId
|
|
215
|
+
messageId: actionToArbitrum.messageId!,
|
|
216
216
|
origin: 'anvil1',
|
|
217
217
|
destination: 'anvil2',
|
|
218
218
|
},
|
|
@@ -236,7 +236,6 @@ describe('MinAmountStrategy E2E', function () {
|
|
|
236
236
|
activeIntents[0].id,
|
|
237
237
|
);
|
|
238
238
|
expect(completedIntent!.status).to.equal('complete');
|
|
239
|
-
expect(completedIntent!.fulfilledAmount).to.equal(70000000n);
|
|
240
239
|
});
|
|
241
240
|
|
|
242
241
|
it('should handle stuck transfer and propose routes to destination', async function () {
|
|
@@ -194,7 +194,7 @@ describe('WeightedStrategy E2E', function () {
|
|
|
194
194
|
hyperlaneCore,
|
|
195
195
|
{
|
|
196
196
|
dispatchTx: rebalanceTxReceipt,
|
|
197
|
-
messageId: actionToBase.messageId
|
|
197
|
+
messageId: actionToBase.messageId!,
|
|
198
198
|
origin: 'anvil1',
|
|
199
199
|
destination: 'anvil3',
|
|
200
200
|
},
|
|
@@ -218,7 +218,6 @@ describe('WeightedStrategy E2E', function () {
|
|
|
218
218
|
activeIntents[0].id,
|
|
219
219
|
);
|
|
220
220
|
expect(completedIntent!.status).to.equal('complete');
|
|
221
|
-
expect(completedIntent!.fulfilledAmount).to.equal(1000000000n);
|
|
222
221
|
|
|
223
222
|
// Assert: No more in-progress actions
|
|
224
223
|
const remainingActions = await context.tracker.getInProgressActions();
|
|
@@ -11,35 +11,47 @@ import {
|
|
|
11
11
|
WarpCore,
|
|
12
12
|
type WarpCoreConfig,
|
|
13
13
|
} from '@hyperlane-xyz/sdk';
|
|
14
|
-
import { objMap } from '@hyperlane-xyz/utils';
|
|
14
|
+
import { objMap, toWei } from '@hyperlane-xyz/utils';
|
|
15
15
|
|
|
16
|
+
import { LiFiBridge } from '../bridges/LiFiBridge.js';
|
|
16
17
|
import { type RebalancerConfig } from '../config/RebalancerConfig.js';
|
|
17
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ExecutionType,
|
|
20
|
+
ExternalBridgeType,
|
|
21
|
+
getAllBridges,
|
|
22
|
+
getStrategyChainConfig,
|
|
23
|
+
getStrategyChainNames,
|
|
24
|
+
} from '../config/types.js';
|
|
25
|
+
import { InventoryRebalancer } from '../core/InventoryRebalancer.js';
|
|
18
26
|
import { Rebalancer } from '../core/Rebalancer.js';
|
|
27
|
+
import { RebalancerOrchestrator } from '../core/RebalancerOrchestrator.js';
|
|
28
|
+
import type { ExternalBridgeRegistry } from '../interfaces/IExternalBridge.js';
|
|
19
29
|
import type { IRebalancer } from '../interfaces/IRebalancer.js';
|
|
20
30
|
import type { IStrategy } from '../interfaces/IStrategy.js';
|
|
21
31
|
import { Metrics } from '../metrics/Metrics.js';
|
|
22
32
|
import { PriceGetter } from '../metrics/PriceGetter.js';
|
|
23
|
-
import { Monitor } from '../monitor/Monitor.js';
|
|
33
|
+
import { type InventoryMonitorConfig, Monitor } from '../monitor/Monitor.js';
|
|
24
34
|
import { StrategyFactory } from '../strategy/StrategyFactory.js';
|
|
25
35
|
import {
|
|
26
36
|
ActionTracker,
|
|
27
37
|
type ActionTrackerConfig,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
} from '../tracking/ActionTracker.js';
|
|
39
|
+
import type { IActionTracker } from '../tracking/IActionTracker.js';
|
|
40
|
+
import { InflightContextAdapter } from '../tracking/InflightContextAdapter.js';
|
|
41
|
+
import { InMemoryStore } from '../tracking/store/index.js';
|
|
42
|
+
import type {
|
|
43
|
+
RebalanceAction,
|
|
44
|
+
RebalanceActionStatus,
|
|
45
|
+
RebalanceIntent,
|
|
46
|
+
RebalanceIntentStatus,
|
|
47
|
+
Transfer,
|
|
48
|
+
TransferStatus,
|
|
49
|
+
} from '../tracking/types.js';
|
|
38
50
|
import {
|
|
39
51
|
ExplorerClient,
|
|
40
52
|
type IExplorerClient,
|
|
41
53
|
} from '../utils/ExplorerClient.js';
|
|
42
|
-
import { isCollateralizedTokenEligibleForRebalancing } from '../utils/
|
|
54
|
+
import { isCollateralizedTokenEligibleForRebalancing } from '../utils/tokenUtils.js';
|
|
43
55
|
|
|
44
56
|
const DEFAULT_EXPLORER_URL =
|
|
45
57
|
process.env.EXPLORER_API_URL || 'https://explorer4.hasura.app/v1/graphql';
|
|
@@ -49,7 +61,8 @@ export class RebalancerContextFactory {
|
|
|
49
61
|
* @param config - The rebalancer config
|
|
50
62
|
* @param warpCore - An instance of `WarpCore` configured for the specified `warpRouteId`.
|
|
51
63
|
* @param tokensByChainName - A map of chain->token to ease the lookup of token by chain
|
|
52
|
-
* @param multiProvider - MultiProvider instance
|
|
64
|
+
* @param multiProvider - MultiProvider instance (for movable collateral operations)
|
|
65
|
+
* @param inventoryMultiProvider - MultiProvider instance for inventory operations (optional)
|
|
53
66
|
* @param multiProtocolProvider - MultiProtocolProvider instance (with mailbox metadata)
|
|
54
67
|
* @param registry - IRegistry instance
|
|
55
68
|
* @param logger - Logger instance
|
|
@@ -59,14 +72,24 @@ export class RebalancerContextFactory {
|
|
|
59
72
|
private readonly warpCore: WarpCore,
|
|
60
73
|
private readonly tokensByChainName: ChainMap<Token>,
|
|
61
74
|
private readonly multiProvider: MultiProvider,
|
|
75
|
+
private readonly inventoryMultiProvider: MultiProvider | undefined,
|
|
62
76
|
private readonly multiProtocolProvider: MultiProtocolProvider,
|
|
63
77
|
private readonly registry: IRegistry,
|
|
64
78
|
private readonly logger: Logger,
|
|
65
79
|
) {}
|
|
66
80
|
|
|
81
|
+
/**
|
|
82
|
+
* @param config - The rebalancer config
|
|
83
|
+
* @param multiProvider - MultiProvider instance (for movable collateral operations)
|
|
84
|
+
* @param inventoryMultiProvider - MultiProvider instance for inventory operations (optional)
|
|
85
|
+
* @param multiProtocolProvider - MultiProtocolProvider instance (optional, created from multiProvider if not provided)
|
|
86
|
+
* @param registry - IRegistry instance
|
|
87
|
+
* @param logger - Logger instance
|
|
88
|
+
*/
|
|
67
89
|
public static async create(
|
|
68
90
|
config: RebalancerConfig,
|
|
69
91
|
multiProvider: MultiProvider,
|
|
92
|
+
inventoryMultiProvider: MultiProvider | undefined,
|
|
70
93
|
multiProtocolProvider: MultiProtocolProvider | undefined,
|
|
71
94
|
registry: IRegistry,
|
|
72
95
|
logger: Logger,
|
|
@@ -78,18 +101,15 @@ export class RebalancerContextFactory {
|
|
|
78
101
|
},
|
|
79
102
|
'Creating RebalancerContextFactory',
|
|
80
103
|
);
|
|
104
|
+
|
|
105
|
+
// TODO: should we pull addressed for chains we care about, i.e those in the warp config
|
|
81
106
|
const addresses = await registry.getAddresses();
|
|
82
107
|
|
|
83
108
|
// The Sealevel warp adapters require the Mailbox address, so we
|
|
84
109
|
// get mailboxes for all chains and merge them with the chain metadata.
|
|
85
110
|
const mailboxes = objMap(addresses, (_, { mailbox }) => ({ mailbox }));
|
|
86
111
|
|
|
87
|
-
//
|
|
88
|
-
const mpp =
|
|
89
|
-
multiProtocolProvider ??
|
|
90
|
-
MultiProtocolProvider.fromMultiProvider(multiProvider);
|
|
91
|
-
const extendedMultiProtocolProvider = mpp.extendChainMetadata(mailboxes);
|
|
92
|
-
|
|
112
|
+
// Fetch warp route config FIRST to get chain list
|
|
93
113
|
const warpCoreConfig =
|
|
94
114
|
warpCoreConfigOverride ??
|
|
95
115
|
(await registry.getWarpRoute(config.warpRouteId));
|
|
@@ -98,6 +118,22 @@ export class RebalancerContextFactory {
|
|
|
98
118
|
`Warp route config for ${config.warpRouteId} not found in registry`,
|
|
99
119
|
);
|
|
100
120
|
}
|
|
121
|
+
|
|
122
|
+
// Force-initialize providers for all warp route chains
|
|
123
|
+
// This ensures fromMultiProvider() snapshots actual provider instances
|
|
124
|
+
const warpChains = [
|
|
125
|
+
...new Set(warpCoreConfig.tokens.map((t: any) => t.chainName)),
|
|
126
|
+
];
|
|
127
|
+
for (const chain of warpChains) {
|
|
128
|
+
multiProvider.getProvider(chain);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Create MultiProtocolProvider (convert from MultiProvider if not provided)
|
|
132
|
+
const mpp =
|
|
133
|
+
multiProtocolProvider ??
|
|
134
|
+
MultiProtocolProvider.fromMultiProvider(multiProvider);
|
|
135
|
+
const extendedMultiProtocolProvider = mpp.extendChainMetadata(mailboxes);
|
|
136
|
+
|
|
101
137
|
const warpCore = WarpCore.FromConfig(
|
|
102
138
|
extendedMultiProtocolProvider,
|
|
103
139
|
warpCoreConfig,
|
|
@@ -117,6 +153,7 @@ export class RebalancerContextFactory {
|
|
|
117
153
|
warpCore,
|
|
118
154
|
tokensByChainName,
|
|
119
155
|
multiProvider,
|
|
156
|
+
inventoryMultiProvider,
|
|
120
157
|
extendedMultiProtocolProvider,
|
|
121
158
|
registry,
|
|
122
159
|
logger,
|
|
@@ -154,7 +191,10 @@ export class RebalancerContextFactory {
|
|
|
154
191
|
);
|
|
155
192
|
}
|
|
156
193
|
|
|
157
|
-
public createMonitor(
|
|
194
|
+
public createMonitor(
|
|
195
|
+
checkFrequency: number,
|
|
196
|
+
inventoryConfig?: InventoryMonitorConfig,
|
|
197
|
+
): Monitor {
|
|
158
198
|
this.logger.debug(
|
|
159
199
|
{
|
|
160
200
|
warpRouteId: this.config.warpRouteId,
|
|
@@ -162,7 +202,12 @@ export class RebalancerContextFactory {
|
|
|
162
202
|
},
|
|
163
203
|
'Creating Monitor',
|
|
164
204
|
);
|
|
165
|
-
return new Monitor(
|
|
205
|
+
return new Monitor(
|
|
206
|
+
checkFrequency,
|
|
207
|
+
this.warpCore,
|
|
208
|
+
this.logger,
|
|
209
|
+
inventoryConfig,
|
|
210
|
+
);
|
|
166
211
|
}
|
|
167
212
|
|
|
168
213
|
public async createStrategy(metrics?: Metrics): Promise<IStrategy> {
|
|
@@ -177,16 +222,48 @@ export class RebalancerContextFactory {
|
|
|
177
222
|
},
|
|
178
223
|
'Creating Strategy',
|
|
179
224
|
);
|
|
225
|
+
|
|
226
|
+
// Build minAmountsByChain from chain configs
|
|
227
|
+
const chainNames = getStrategyChainNames(this.config.strategyConfig);
|
|
228
|
+
const minAmountsByChain: ChainMap<bigint> = {};
|
|
229
|
+
|
|
230
|
+
for (const chainName of chainNames) {
|
|
231
|
+
const chainConfig = getStrategyChainConfig(
|
|
232
|
+
this.config.strategyConfig,
|
|
233
|
+
chainName,
|
|
234
|
+
);
|
|
235
|
+
if (chainConfig?.bridgeMinAcceptedAmount) {
|
|
236
|
+
const token = this.tokensByChainName[chainName];
|
|
237
|
+
const decimals = token?.decimals ?? 18;
|
|
238
|
+
minAmountsByChain[chainName] = BigInt(
|
|
239
|
+
toWei(chainConfig.bridgeMinAcceptedAmount, decimals),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
this.logger.debug(
|
|
245
|
+
{
|
|
246
|
+
minAmountsByChain: Object.fromEntries(
|
|
247
|
+
Object.entries(minAmountsByChain).map(([k, v]) => [k, v.toString()]),
|
|
248
|
+
),
|
|
249
|
+
},
|
|
250
|
+
'Built minimum amounts by chain for strategy',
|
|
251
|
+
);
|
|
252
|
+
|
|
180
253
|
return StrategyFactory.createStrategy(
|
|
181
254
|
this.config.strategyConfig,
|
|
182
255
|
this.tokensByChainName,
|
|
183
256
|
await this.getInitialTotalCollateral(),
|
|
184
257
|
this.logger,
|
|
185
258
|
metrics,
|
|
259
|
+
minAmountsByChain,
|
|
186
260
|
);
|
|
187
261
|
}
|
|
188
262
|
|
|
189
|
-
|
|
263
|
+
private createMovableCollateralRebalancer(
|
|
264
|
+
actionTracker: IActionTracker,
|
|
265
|
+
metrics?: Metrics,
|
|
266
|
+
): IRebalancer {
|
|
190
267
|
this.logger.debug(
|
|
191
268
|
{ warpRouteId: this.config.warpRouteId },
|
|
192
269
|
'Creating Rebalancer',
|
|
@@ -197,6 +274,7 @@ export class RebalancerContextFactory {
|
|
|
197
274
|
this.multiProvider.metadata,
|
|
198
275
|
this.tokensByChainName,
|
|
199
276
|
this.multiProvider,
|
|
277
|
+
actionTracker,
|
|
200
278
|
this.logger,
|
|
201
279
|
metrics,
|
|
202
280
|
);
|
|
@@ -272,6 +350,7 @@ export class RebalancerContextFactory {
|
|
|
272
350
|
routersByDomain,
|
|
273
351
|
bridges,
|
|
274
352
|
rebalancerAddress,
|
|
353
|
+
inventorySignerAddress: this.config.inventorySigner,
|
|
275
354
|
};
|
|
276
355
|
|
|
277
356
|
// 6. Create ActionTracker
|
|
@@ -301,6 +380,196 @@ export class RebalancerContextFactory {
|
|
|
301
380
|
return { tracker, adapter };
|
|
302
381
|
}
|
|
303
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Creates inventory components for inventory-based rebalancing.
|
|
385
|
+
* Returns null if inventory config is not available.
|
|
386
|
+
*
|
|
387
|
+
* @param actionTracker - ActionTracker instance for tracking inventory actions
|
|
388
|
+
*/
|
|
389
|
+
private async createInventoryRebalancerAndConfig(
|
|
390
|
+
actionTracker: IActionTracker,
|
|
391
|
+
): Promise<{
|
|
392
|
+
inventoryRebalancer: IRebalancer;
|
|
393
|
+
externalBridgeRegistry: Partial<ExternalBridgeRegistry>;
|
|
394
|
+
inventoryConfig: InventoryMonitorConfig;
|
|
395
|
+
} | null> {
|
|
396
|
+
const { inventorySigner, externalBridges } = this.config;
|
|
397
|
+
|
|
398
|
+
if (!inventorySigner) {
|
|
399
|
+
this.logger.debug(
|
|
400
|
+
'Inventory config not available, skipping inventory components creation',
|
|
401
|
+
);
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
this.logger.debug(
|
|
406
|
+
{ warpRouteId: this.config.warpRouteId, inventorySigner },
|
|
407
|
+
'Creating inventory components',
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
const inventoryChains = getStrategyChainNames(
|
|
411
|
+
this.config.strategyConfig,
|
|
412
|
+
).filter((chainName) => {
|
|
413
|
+
const chainConfig = getStrategyChainConfig(
|
|
414
|
+
this.config.strategyConfig,
|
|
415
|
+
chainName,
|
|
416
|
+
);
|
|
417
|
+
return chainConfig?.executionType === ExecutionType.Inventory;
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
if (inventoryChains.length === 0) {
|
|
421
|
+
this.logger.debug('No inventory chains configured');
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Build registry dynamically from ExternalBridgeType enum
|
|
426
|
+
const externalBridgeRegistry: Partial<ExternalBridgeRegistry> = {};
|
|
427
|
+
|
|
428
|
+
for (const bridgeType of Object.values(ExternalBridgeType)) {
|
|
429
|
+
switch (bridgeType) {
|
|
430
|
+
case ExternalBridgeType.LiFi: {
|
|
431
|
+
const lifiConfig = externalBridges?.lifi;
|
|
432
|
+
if (lifiConfig?.integrator) {
|
|
433
|
+
externalBridgeRegistry[ExternalBridgeType.LiFi] = new LiFiBridge(
|
|
434
|
+
{
|
|
435
|
+
integrator: lifiConfig.integrator,
|
|
436
|
+
defaultSlippage: lifiConfig.defaultSlippage,
|
|
437
|
+
chainMetadata: this.multiProvider.metadata,
|
|
438
|
+
},
|
|
439
|
+
this.logger,
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
default: {
|
|
445
|
+
// Exhaustive check - TypeScript will error if new enum value added
|
|
446
|
+
const _exhaustive: never = bridgeType;
|
|
447
|
+
throw new Error(`Unknown bridge type: ${_exhaustive}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (Object.keys(externalBridgeRegistry).length === 0) {
|
|
453
|
+
this.logger.debug(
|
|
454
|
+
'No external bridges configured, skipping inventory components',
|
|
455
|
+
);
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// 3. Build inventory config
|
|
460
|
+
const inventoryConfig: InventoryMonitorConfig = {
|
|
461
|
+
inventoryAddress: inventorySigner,
|
|
462
|
+
chains: inventoryChains,
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// 4. Create InventoryRebalancer
|
|
466
|
+
// Use inventoryMultiProvider for inventory operations if available, otherwise fall back to multiProvider
|
|
467
|
+
const inventoryRebalancer = new InventoryRebalancer(
|
|
468
|
+
{
|
|
469
|
+
inventorySigner,
|
|
470
|
+
inventoryMultiProvider: this.inventoryMultiProvider,
|
|
471
|
+
inventoryChains,
|
|
472
|
+
},
|
|
473
|
+
actionTracker,
|
|
474
|
+
externalBridgeRegistry,
|
|
475
|
+
this.warpCore,
|
|
476
|
+
this.multiProvider,
|
|
477
|
+
this.logger,
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
this.logger.info(
|
|
481
|
+
{
|
|
482
|
+
inventoryChains,
|
|
483
|
+
inventorySigner,
|
|
484
|
+
},
|
|
485
|
+
'Inventory components created successfully',
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
return { inventoryRebalancer, externalBridgeRegistry, inventoryConfig };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Creates all rebalancers based on config execution types.
|
|
493
|
+
* Returns an array of rebalancers (movableCollateral and/or inventory)
|
|
494
|
+
* along with metadata needed for monitor and orchestrator.
|
|
495
|
+
*/
|
|
496
|
+
public async createRebalancers(
|
|
497
|
+
actionTracker: IActionTracker,
|
|
498
|
+
metrics?: Metrics,
|
|
499
|
+
): Promise<{
|
|
500
|
+
rebalancers: IRebalancer[];
|
|
501
|
+
externalBridgeRegistry: Partial<ExternalBridgeRegistry>;
|
|
502
|
+
inventoryConfig?: InventoryMonitorConfig;
|
|
503
|
+
}> {
|
|
504
|
+
const rebalancers: IRebalancer[] = [];
|
|
505
|
+
let externalBridgeRegistry: Partial<ExternalBridgeRegistry> = {};
|
|
506
|
+
let inventoryConfig: InventoryMonitorConfig | undefined;
|
|
507
|
+
|
|
508
|
+
// Check if any chains use movableCollateral execution type
|
|
509
|
+
const hasMovableCollateral = this.hasMovableCollateralChains();
|
|
510
|
+
if (hasMovableCollateral) {
|
|
511
|
+
const rebalancer = this.createMovableCollateralRebalancer(
|
|
512
|
+
actionTracker,
|
|
513
|
+
metrics,
|
|
514
|
+
);
|
|
515
|
+
rebalancers.push(rebalancer);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Check if any chains use inventory execution type
|
|
519
|
+
const inventoryComponents =
|
|
520
|
+
await this.createInventoryRebalancerAndConfig(actionTracker);
|
|
521
|
+
if (inventoryComponents) {
|
|
522
|
+
rebalancers.push(inventoryComponents.inventoryRebalancer);
|
|
523
|
+
externalBridgeRegistry = inventoryComponents.externalBridgeRegistry;
|
|
524
|
+
inventoryConfig = inventoryComponents.inventoryConfig;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return { rebalancers, externalBridgeRegistry, inventoryConfig };
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Creates a RebalancerOrchestrator with all required dependencies.
|
|
532
|
+
*/
|
|
533
|
+
public createOrchestrator(options: {
|
|
534
|
+
strategy: IStrategy;
|
|
535
|
+
actionTracker: IActionTracker;
|
|
536
|
+
inflightContextAdapter: InflightContextAdapter;
|
|
537
|
+
rebalancers: IRebalancer[];
|
|
538
|
+
externalBridgeRegistry: Partial<ExternalBridgeRegistry>;
|
|
539
|
+
metrics?: Metrics;
|
|
540
|
+
}): RebalancerOrchestrator {
|
|
541
|
+
this.logger.debug(
|
|
542
|
+
{ warpRouteId: this.config.warpRouteId },
|
|
543
|
+
'Creating RebalancerOrchestrator',
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
return new RebalancerOrchestrator({
|
|
547
|
+
strategy: options.strategy,
|
|
548
|
+
actionTracker: options.actionTracker,
|
|
549
|
+
inflightContextAdapter: options.inflightContextAdapter,
|
|
550
|
+
rebalancerConfig: this.config,
|
|
551
|
+
logger: this.logger,
|
|
552
|
+
rebalancers: options.rebalancers,
|
|
553
|
+
externalBridgeRegistry: options.externalBridgeRegistry,
|
|
554
|
+
metrics: options.metrics,
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private hasMovableCollateralChains(): boolean {
|
|
559
|
+
return getStrategyChainNames(this.config.strategyConfig).some(
|
|
560
|
+
(chainName) => {
|
|
561
|
+
const chainConfig = getStrategyChainConfig(
|
|
562
|
+
this.config.strategyConfig,
|
|
563
|
+
chainName,
|
|
564
|
+
);
|
|
565
|
+
return (
|
|
566
|
+
chainConfig?.executionType === ExecutionType.MovableCollateral ||
|
|
567
|
+
chainConfig?.executionType === undefined
|
|
568
|
+
); // Default is movableCollateral
|
|
569
|
+
},
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
|
|
304
573
|
private async getInitialTotalCollateral(): Promise<bigint> {
|
|
305
574
|
let initialTotalCollateral = 0n;
|
|
306
575
|
|
package/src/index.ts
CHANGED
|
@@ -57,16 +57,23 @@ export { PriceGetter } from './metrics/PriceGetter.js';
|
|
|
57
57
|
|
|
58
58
|
// Interfaces
|
|
59
59
|
export type {
|
|
60
|
+
ExecutionResult,
|
|
61
|
+
IInventoryRebalancer,
|
|
62
|
+
IMovableCollateralRebalancer,
|
|
60
63
|
IRebalancer,
|
|
64
|
+
InventoryExecutionResult,
|
|
65
|
+
MovableCollateralExecutionResult,
|
|
61
66
|
PreparedTransaction,
|
|
62
|
-
|
|
63
|
-
RebalanceExecutionResult,
|
|
67
|
+
RebalancerType,
|
|
64
68
|
} from './interfaces/IRebalancer.js';
|
|
65
69
|
export type {
|
|
66
70
|
IStrategy,
|
|
67
|
-
StrategyRoute,
|
|
68
|
-
RawBalances,
|
|
69
71
|
InflightContext,
|
|
72
|
+
InventoryRoute,
|
|
73
|
+
MovableCollateralRoute,
|
|
74
|
+
RawBalances,
|
|
75
|
+
Route,
|
|
76
|
+
StrategyRoute,
|
|
70
77
|
} from './interfaces/IStrategy.js';
|
|
71
78
|
export type {
|
|
72
79
|
ConfirmedBlockTag,
|
|
@@ -82,10 +89,16 @@ export {
|
|
|
82
89
|
export type { IMetrics } from './interfaces/IMetrics.js';
|
|
83
90
|
|
|
84
91
|
// Utils
|
|
85
|
-
export {
|
|
92
|
+
export {
|
|
93
|
+
getBridgeConfig,
|
|
94
|
+
isMovableCollateralConfig,
|
|
95
|
+
isInventoryConfig,
|
|
96
|
+
} from './utils/bridgeUtils.js';
|
|
86
97
|
export type {
|
|
87
98
|
BridgeConfigWithOverride,
|
|
88
99
|
BridgeConfig,
|
|
100
|
+
MovableCollateralBridgeConfig,
|
|
101
|
+
InventoryBridgeConfig,
|
|
89
102
|
} from './utils/bridgeUtils.js';
|
|
90
103
|
export { getRawBalances } from './utils/balanceUtils.js';
|
|
91
104
|
export { isCollateralizedTokenEligibleForRebalancing } from './utils/tokenUtils.js';
|
|
@@ -102,6 +115,8 @@ export type {
|
|
|
102
115
|
Transfer,
|
|
103
116
|
RebalanceIntent,
|
|
104
117
|
RebalanceAction,
|
|
118
|
+
ActionType,
|
|
119
|
+
PartialInventoryIntent,
|
|
105
120
|
} from './tracking/types.js';
|
|
106
121
|
|
|
107
122
|
// Factory
|