@hyperlane-xyz/rebalancer 2.0.0 → 3.1.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 +8 -2
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +9 -4
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +135 -1
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +1023 -304
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +113 -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 +892 -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 +1382 -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 +719 -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 +74 -110
- 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/ForkIndexer.d.ts.map +1 -1
- package/dist/e2e/harness/ForkIndexer.js +1 -0
- package/dist/e2e/harness/ForkIndexer.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 +9 -9
- 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 +171 -17
- 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 +2 -2
- 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 +34 -1
- package/dist/tracking/ActionTracker.d.ts.map +1 -1
- package/dist/tracking/ActionTracker.js +233 -26
- package/dist/tracking/ActionTracker.js.map +1 -1
- package/dist/tracking/ActionTracker.test.js +380 -19
- package/dist/tracking/ActionTracker.test.js.map +1 -1
- package/dist/tracking/IActionTracker.d.ts +48 -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 +33 -2
- package/dist/tracking/types.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.d.ts +3 -1
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +16 -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 +162 -0
- package/src/config/RebalancerConfig.ts +21 -3
- package/src/config/types.ts +147 -10
- package/src/core/InventoryRebalancer.test.ts +1721 -0
- package/src/core/InventoryRebalancer.ts +1265 -0
- package/src/core/Rebalancer.test.ts +84 -30
- package/src/core/Rebalancer.ts +144 -23
- package/src/core/RebalancerOrchestrator.test.ts +869 -0
- package/src/core/RebalancerOrchestrator.ts +146 -95
- package/src/core/RebalancerService.test.ts +86 -124
- 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/ForkIndexer.ts +1 -0
- package/src/e2e/harness/TestHelpers.ts +1 -4
- package/src/e2e/harness/TestRebalancer.ts +10 -7
- package/src/e2e/minAmount.e2e-test.ts +1 -2
- package/src/e2e/weighted.e2e-test.ts +1 -2
- package/src/factories/RebalancerContextFactory.ts +294 -24
- package/src/index.ts +22 -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 +443 -19
- package/src/tracking/ActionTracker.ts +339 -28
- package/src/tracking/IActionTracker.ts +59 -3
- package/src/tracking/InflightContextAdapter.test.ts +7 -4
- package/src/tracking/InflightContextAdapter.ts +42 -9
- package/src/tracking/types.ts +45 -2
- package/src/utils/ExplorerClient.ts +27 -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
|
@@ -3,12 +3,17 @@ import { type Logger } from 'pino';
|
|
|
3
3
|
import { type ChainMap, type Token } from '@hyperlane-xyz/sdk';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
+
ExecutionType,
|
|
6
7
|
RebalancerStrategyOptions,
|
|
7
8
|
type StrategyConfig,
|
|
8
9
|
} from '../config/types.js';
|
|
9
10
|
import { type IStrategy } from '../interfaces/IStrategy.js';
|
|
10
11
|
import { type Metrics } from '../metrics/Metrics.js';
|
|
11
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
BridgeConfigWithOverride,
|
|
14
|
+
InventoryBridgeConfig,
|
|
15
|
+
MovableCollateralBridgeConfig,
|
|
16
|
+
} from '../utils/bridgeUtils.js';
|
|
12
17
|
|
|
13
18
|
import { CollateralDeficitStrategy } from './CollateralDeficitStrategy.js';
|
|
14
19
|
import { CompositeStrategy } from './CompositeStrategy.js';
|
|
@@ -26,6 +31,7 @@ export class StrategyFactory {
|
|
|
26
31
|
* @param initialTotalCollateral The initial total collateral of the rebalancer
|
|
27
32
|
* @param logger The logger to use for the strategy
|
|
28
33
|
* @param metrics The metrics to use for the strategy
|
|
34
|
+
* @param minAmountsByChain Optional minimum amounts per chain for filtering routes
|
|
29
35
|
* @returns A concrete strategy implementation
|
|
30
36
|
*/
|
|
31
37
|
static createStrategy(
|
|
@@ -34,6 +40,7 @@ export class StrategyFactory {
|
|
|
34
40
|
initialTotalCollateral: bigint,
|
|
35
41
|
logger: Logger,
|
|
36
42
|
metrics?: Metrics,
|
|
43
|
+
minAmountsByChain?: ChainMap<bigint>,
|
|
37
44
|
): IStrategy {
|
|
38
45
|
if (strategyConfigs.length === 0) {
|
|
39
46
|
throw new Error('At least one strategy must be configured');
|
|
@@ -47,6 +54,7 @@ export class StrategyFactory {
|
|
|
47
54
|
initialTotalCollateral,
|
|
48
55
|
logger,
|
|
49
56
|
metrics,
|
|
57
|
+
minAmountsByChain,
|
|
50
58
|
);
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -58,6 +66,7 @@ export class StrategyFactory {
|
|
|
58
66
|
initialTotalCollateral,
|
|
59
67
|
logger,
|
|
60
68
|
metrics,
|
|
69
|
+
minAmountsByChain,
|
|
61
70
|
),
|
|
62
71
|
);
|
|
63
72
|
return new CompositeStrategy(subStrategies, logger);
|
|
@@ -72,6 +81,7 @@ export class StrategyFactory {
|
|
|
72
81
|
initialTotalCollateral: bigint,
|
|
73
82
|
logger: Logger,
|
|
74
83
|
metrics?: Metrics,
|
|
84
|
+
_minAmountsByChain?: ChainMap<bigint>,
|
|
75
85
|
): IStrategy {
|
|
76
86
|
const bridgeConfigs = this.extractBridgeConfigs(strategyConfig);
|
|
77
87
|
|
|
@@ -116,13 +126,30 @@ export class StrategyFactory {
|
|
|
116
126
|
const bridgeConfigs: ChainMap<BridgeConfigWithOverride> = {};
|
|
117
127
|
|
|
118
128
|
for (const [chain, config] of Object.entries(strategyConfig.chains)) {
|
|
119
|
-
|
|
120
|
-
bridge: config.bridge,
|
|
129
|
+
const baseConfig = {
|
|
121
130
|
bridgeMinAcceptedAmount: config.bridgeMinAcceptedAmount ?? 0,
|
|
122
|
-
override: config.override as ChainMap<
|
|
123
|
-
Partial<{ bridge: string; bridgeMinAcceptedAmount: string | number }>
|
|
124
|
-
>,
|
|
125
131
|
};
|
|
132
|
+
|
|
133
|
+
const executionType =
|
|
134
|
+
config.executionType ?? ExecutionType.MovableCollateral;
|
|
135
|
+
|
|
136
|
+
if (executionType === ExecutionType.Inventory) {
|
|
137
|
+
bridgeConfigs[chain] = {
|
|
138
|
+
...baseConfig,
|
|
139
|
+
executionType: 'inventory',
|
|
140
|
+
externalBridge: config.externalBridge!, // Validated by config schema
|
|
141
|
+
override: config.override as ChainMap<Partial<InventoryBridgeConfig>>,
|
|
142
|
+
};
|
|
143
|
+
} else {
|
|
144
|
+
bridgeConfigs[chain] = {
|
|
145
|
+
...baseConfig,
|
|
146
|
+
executionType: 'movableCollateral',
|
|
147
|
+
bridge: config.bridge!, // Validated by config schema
|
|
148
|
+
override: config.override as ChainMap<
|
|
149
|
+
Partial<MovableCollateralBridgeConfig>
|
|
150
|
+
>,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
126
153
|
}
|
|
127
154
|
|
|
128
155
|
return bridgeConfigs;
|
|
@@ -258,6 +258,7 @@ describe('WeightedStrategy', () => {
|
|
|
258
258
|
destination: chain1,
|
|
259
259
|
amount: ethers.utils.parseEther('50').toBigInt(),
|
|
260
260
|
bridge: ethers.constants.AddressZero,
|
|
261
|
+
executionType: 'movableCollateral',
|
|
261
262
|
},
|
|
262
263
|
]);
|
|
263
264
|
});
|
|
@@ -325,6 +326,7 @@ describe('WeightedStrategy', () => {
|
|
|
325
326
|
destination: chain1,
|
|
326
327
|
amount: ethers.utils.parseEther('100').toBigInt(),
|
|
327
328
|
bridge: ethers.constants.AddressZero,
|
|
329
|
+
executionType: 'movableCollateral',
|
|
328
330
|
},
|
|
329
331
|
]);
|
|
330
332
|
});
|
|
@@ -363,12 +365,14 @@ describe('WeightedStrategy', () => {
|
|
|
363
365
|
destination: chain1,
|
|
364
366
|
amount: 133333333333333333333n,
|
|
365
367
|
bridge: ethers.constants.AddressZero,
|
|
368
|
+
executionType: 'movableCollateral',
|
|
366
369
|
},
|
|
367
370
|
{
|
|
368
371
|
origin: chain3,
|
|
369
372
|
destination: chain2,
|
|
370
373
|
amount: 133333333333333333333n,
|
|
371
374
|
bridge: ethers.constants.AddressZero,
|
|
375
|
+
executionType: 'movableCollateral',
|
|
372
376
|
},
|
|
373
377
|
]);
|
|
374
378
|
});
|
|
@@ -408,12 +412,14 @@ describe('WeightedStrategy', () => {
|
|
|
408
412
|
destination: chain1,
|
|
409
413
|
amount: ethers.utils.parseEther('25').toBigInt(),
|
|
410
414
|
bridge: ethers.constants.AddressZero,
|
|
415
|
+
executionType: 'movableCollateral',
|
|
411
416
|
},
|
|
412
417
|
{
|
|
413
418
|
origin: chain3,
|
|
414
419
|
destination: chain1,
|
|
415
420
|
amount: ethers.utils.parseEther('25').toBigInt(),
|
|
416
421
|
bridge: ethers.constants.AddressZero,
|
|
422
|
+
executionType: 'movableCollateral',
|
|
417
423
|
},
|
|
418
424
|
]);
|
|
419
425
|
});
|
package/src/test/helpers.ts
CHANGED
|
@@ -16,18 +16,24 @@ import {
|
|
|
16
16
|
import type { RebalancerConfig } from '../config/RebalancerConfig.js';
|
|
17
17
|
import { RebalancerStrategyOptions } from '../config/types.js';
|
|
18
18
|
import type {
|
|
19
|
+
ExecutionResult,
|
|
19
20
|
IRebalancer,
|
|
21
|
+
MovableCollateralExecutionResult,
|
|
20
22
|
PreparedTransaction,
|
|
21
|
-
|
|
22
|
-
RebalanceRoute,
|
|
23
|
+
RebalancerType,
|
|
23
24
|
} from '../interfaces/IRebalancer.js';
|
|
24
|
-
import type {
|
|
25
|
-
|
|
25
|
+
import type {
|
|
26
|
+
MovableCollateralRoute,
|
|
27
|
+
StrategyRoute,
|
|
28
|
+
} from '../interfaces/IStrategy.js';
|
|
29
|
+
import type { BridgeConfigWithOverride } from '../utils/bridgeUtils.js';
|
|
26
30
|
|
|
27
31
|
// === Mock Classes ===
|
|
28
32
|
|
|
29
33
|
export class MockRebalancer implements IRebalancer {
|
|
30
|
-
|
|
34
|
+
readonly rebalancerType: RebalancerType = 'movableCollateral';
|
|
35
|
+
|
|
36
|
+
rebalance(_routes: MovableCollateralRoute[]): Promise<ExecutionResult[]> {
|
|
31
37
|
return Promise.resolve([]);
|
|
32
38
|
}
|
|
33
39
|
}
|
|
@@ -36,33 +42,45 @@ export class MockRebalancer implements IRebalancer {
|
|
|
36
42
|
|
|
37
43
|
export function buildTestRoute(
|
|
38
44
|
overrides: Partial<StrategyRoute> = {},
|
|
45
|
+
executionType: 'movableCollateral' | 'inventory' = 'movableCollateral',
|
|
39
46
|
): StrategyRoute {
|
|
47
|
+
if (executionType === 'inventory') {
|
|
48
|
+
return {
|
|
49
|
+
origin: 'ethereum',
|
|
50
|
+
destination: 'arbitrum',
|
|
51
|
+
amount: ethers.utils.parseEther('100').toBigInt(),
|
|
52
|
+
executionType: 'inventory',
|
|
53
|
+
externalBridge: 'lifi',
|
|
54
|
+
...overrides,
|
|
55
|
+
} as StrategyRoute;
|
|
56
|
+
}
|
|
40
57
|
return {
|
|
41
58
|
origin: 'ethereum',
|
|
42
59
|
destination: 'arbitrum',
|
|
43
60
|
amount: ethers.utils.parseEther('100').toBigInt(),
|
|
61
|
+
executionType: 'movableCollateral',
|
|
44
62
|
bridge: TEST_ADDRESSES.bridge,
|
|
45
63
|
...overrides,
|
|
46
|
-
};
|
|
64
|
+
} as StrategyRoute;
|
|
47
65
|
}
|
|
48
66
|
|
|
49
|
-
export function
|
|
50
|
-
overrides: Partial<
|
|
51
|
-
):
|
|
67
|
+
export function buildTestMovableCollateralRoute(
|
|
68
|
+
overrides: Partial<MovableCollateralRoute> = {},
|
|
69
|
+
): MovableCollateralRoute {
|
|
52
70
|
return {
|
|
53
|
-
intentId: overrides.intentId ?? `test-route-${Date.now()}`,
|
|
54
71
|
origin: 'ethereum',
|
|
55
72
|
destination: 'arbitrum',
|
|
56
73
|
amount: ethers.utils.parseEther('100').toBigInt(),
|
|
74
|
+
executionType: 'movableCollateral',
|
|
57
75
|
bridge: TEST_ADDRESSES.bridge,
|
|
58
76
|
...overrides,
|
|
59
77
|
};
|
|
60
78
|
}
|
|
61
79
|
|
|
62
80
|
export function buildTestResult(
|
|
63
|
-
overrides: Partial<
|
|
64
|
-
):
|
|
65
|
-
const route = overrides.route ??
|
|
81
|
+
overrides: Partial<MovableCollateralExecutionResult> = {},
|
|
82
|
+
): MovableCollateralExecutionResult {
|
|
83
|
+
const route = overrides.route ?? buildTestMovableCollateralRoute();
|
|
66
84
|
return {
|
|
67
85
|
route,
|
|
68
86
|
success: true,
|
|
@@ -77,7 +95,12 @@ export function buildTestResult(
|
|
|
77
95
|
export function buildTestPreparedTransaction(
|
|
78
96
|
overrides: Partial<PreparedTransaction> = {},
|
|
79
97
|
): PreparedTransaction {
|
|
80
|
-
const route =
|
|
98
|
+
const route =
|
|
99
|
+
overrides.route ??
|
|
100
|
+
({
|
|
101
|
+
...buildTestMovableCollateralRoute(),
|
|
102
|
+
intentId: 'test-intent',
|
|
103
|
+
} as MovableCollateralRoute & { intentId: string });
|
|
81
104
|
return {
|
|
82
105
|
populatedTx: {
|
|
83
106
|
to: TEST_ADDRESSES.token,
|
|
@@ -272,6 +295,7 @@ export function buildTestBridges(
|
|
|
272
295
|
): ChainMap<BridgeConfigWithOverride> {
|
|
273
296
|
return chains.reduce((acc, chain) => {
|
|
274
297
|
acc[chain] = {
|
|
298
|
+
executionType: 'movableCollateral',
|
|
275
299
|
bridge: TEST_ADDRESSES.bridge,
|
|
276
300
|
bridgeMinAcceptedAmount: 0,
|
|
277
301
|
};
|
|
@@ -291,6 +315,7 @@ export function extractBridgeConfigs(
|
|
|
291
315
|
): ChainMap<BridgeConfigWithOverride> {
|
|
292
316
|
return Object.entries(chainConfig).reduce((acc, [chain, config]) => {
|
|
293
317
|
acc[chain] = {
|
|
318
|
+
executionType: 'movableCollateral',
|
|
294
319
|
bridge: config.bridge,
|
|
295
320
|
bridgeMinAcceptedAmount: config.bridgeMinAcceptedAmount ?? 0,
|
|
296
321
|
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import Sinon, { type SinonStub } from 'sinon';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
BridgeQuote,
|
|
5
|
+
BridgeTransferStatus,
|
|
6
|
+
} from '../interfaces/IExternalBridge.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create mock functions for LiFi SDK.
|
|
10
|
+
*/
|
|
11
|
+
export function createLiFiSdkMocks() {
|
|
12
|
+
return {
|
|
13
|
+
createConfig: Sinon.stub(),
|
|
14
|
+
getQuote: Sinon.stub(),
|
|
15
|
+
executeRoute: Sinon.stub(),
|
|
16
|
+
getStatus: Sinon.stub(),
|
|
17
|
+
convertQuoteToRoute: Sinon.stub().callsFake((quote: unknown) => {
|
|
18
|
+
const q = quote as Record<string, unknown> & {
|
|
19
|
+
action?: { fromChainId?: number; toChainId?: number };
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
...q,
|
|
23
|
+
fromChainId: q.action?.fromChainId ?? 42161,
|
|
24
|
+
toChainId: q.action?.toChainId ?? 1399811149,
|
|
25
|
+
steps: [],
|
|
26
|
+
};
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Configure a mock getQuote to return a successful quote.
|
|
33
|
+
*/
|
|
34
|
+
export function mockSuccessfulQuote(
|
|
35
|
+
stub: SinonStub,
|
|
36
|
+
overrides?: Partial<{
|
|
37
|
+
id: string;
|
|
38
|
+
tool: string;
|
|
39
|
+
fromAmount: string;
|
|
40
|
+
toAmount: string;
|
|
41
|
+
toAmountMin: string;
|
|
42
|
+
executionDuration: number;
|
|
43
|
+
fromChainId: number;
|
|
44
|
+
toChainId: number;
|
|
45
|
+
}>,
|
|
46
|
+
) {
|
|
47
|
+
const fromChainId = overrides?.fromChainId ?? 42161;
|
|
48
|
+
const toChainId = overrides?.toChainId ?? 1399811149;
|
|
49
|
+
const fromAmount = overrides?.fromAmount ?? '10000000000';
|
|
50
|
+
const toAmount = overrides?.toAmount ?? '9950000000';
|
|
51
|
+
const toAmountMin = overrides?.toAmountMin ?? '9900000000';
|
|
52
|
+
|
|
53
|
+
stub.resolves({
|
|
54
|
+
id: overrides?.id ?? 'quote-123',
|
|
55
|
+
tool: overrides?.tool ?? 'across',
|
|
56
|
+
action: {
|
|
57
|
+
fromAmount,
|
|
58
|
+
fromChainId,
|
|
59
|
+
toChainId,
|
|
60
|
+
},
|
|
61
|
+
estimate: {
|
|
62
|
+
toAmount,
|
|
63
|
+
toAmountMin,
|
|
64
|
+
executionDuration: overrides?.executionDuration ?? 300,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Configure a mock executeRoute to return a successful execution.
|
|
71
|
+
*/
|
|
72
|
+
export function mockSuccessfulExecution(stub: SinonStub, txHash: string) {
|
|
73
|
+
stub.resolves({
|
|
74
|
+
steps: [
|
|
75
|
+
{
|
|
76
|
+
execution: {
|
|
77
|
+
process: [{ txHash }],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Configure a mock getStatus to return a specific status.
|
|
86
|
+
*/
|
|
87
|
+
export function mockLiFiStatus(
|
|
88
|
+
stub: SinonStub,
|
|
89
|
+
status: 'DONE' | 'PENDING' | 'FAILED' | 'NOT_FOUND',
|
|
90
|
+
overrides?: Partial<{
|
|
91
|
+
receivingTxHash: string;
|
|
92
|
+
amount: string;
|
|
93
|
+
substatus: string;
|
|
94
|
+
}>,
|
|
95
|
+
) {
|
|
96
|
+
const responses: Record<string, unknown> = {
|
|
97
|
+
DONE: {
|
|
98
|
+
status: 'DONE',
|
|
99
|
+
receiving: {
|
|
100
|
+
txHash: overrides?.receivingTxHash ?? '0xReceivingTxHash',
|
|
101
|
+
amount: overrides?.amount ?? '9950000000',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
PENDING: {
|
|
105
|
+
status: 'PENDING',
|
|
106
|
+
substatus: overrides?.substatus ?? 'WAIT_SOURCE_CONFIRMATIONS',
|
|
107
|
+
},
|
|
108
|
+
FAILED: {
|
|
109
|
+
status: 'FAILED',
|
|
110
|
+
substatus: overrides?.substatus ?? 'BRIDGE_CALL_FAILED',
|
|
111
|
+
},
|
|
112
|
+
NOT_FOUND: {
|
|
113
|
+
status: 'NOT_FOUND',
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
stub.resolves(responses[status]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a mock BridgeQuote for testing.
|
|
122
|
+
*/
|
|
123
|
+
export function createMockBridgeQuote(
|
|
124
|
+
overrides?: Partial<BridgeQuote>,
|
|
125
|
+
): BridgeQuote {
|
|
126
|
+
return {
|
|
127
|
+
id: 'quote-123',
|
|
128
|
+
tool: 'across',
|
|
129
|
+
fromAmount: 10000000000n,
|
|
130
|
+
toAmount: 9950000000n,
|
|
131
|
+
toAmountMin: 9900000000n,
|
|
132
|
+
executionDuration: 300,
|
|
133
|
+
gasCosts: 50000000n, // Default mock gas costs
|
|
134
|
+
feeCosts: 0n, // Default mock fee costs
|
|
135
|
+
route: {
|
|
136
|
+
action: { fromChainId: 42161, toChainId: 1399811149 },
|
|
137
|
+
},
|
|
138
|
+
...overrides,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Create a mock BridgeTransferStatus for testing.
|
|
144
|
+
*/
|
|
145
|
+
export function createMockBridgeStatus(
|
|
146
|
+
status: 'pending' | 'complete' | 'failed' | 'not_found',
|
|
147
|
+
overrides?: Partial<{
|
|
148
|
+
substatus: string;
|
|
149
|
+
receivingTxHash: string;
|
|
150
|
+
receivedAmount: bigint;
|
|
151
|
+
error: string;
|
|
152
|
+
}>,
|
|
153
|
+
): BridgeTransferStatus {
|
|
154
|
+
switch (status) {
|
|
155
|
+
case 'pending':
|
|
156
|
+
return {
|
|
157
|
+
status: 'pending',
|
|
158
|
+
substatus: overrides?.substatus,
|
|
159
|
+
};
|
|
160
|
+
case 'complete':
|
|
161
|
+
return {
|
|
162
|
+
status: 'complete',
|
|
163
|
+
receivingTxHash: overrides?.receivingTxHash ?? '0xReceivingTxHash',
|
|
164
|
+
receivedAmount: overrides?.receivedAmount ?? 9950000000n,
|
|
165
|
+
};
|
|
166
|
+
case 'failed':
|
|
167
|
+
return {
|
|
168
|
+
status: 'failed',
|
|
169
|
+
error: overrides?.error,
|
|
170
|
+
};
|
|
171
|
+
case 'not_found':
|
|
172
|
+
return { status: 'not_found' };
|
|
173
|
+
}
|
|
174
|
+
}
|