@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
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { pino } from 'pino';
|
|
3
|
+
import { CompositeStrategy } from './CompositeStrategy.js';
|
|
4
|
+
const testLogger = pino({ level: 'silent' });
|
|
5
|
+
const TEST_BRIDGE = '0x1234567890123456789012345678901234567890';
|
|
6
|
+
class MockStrategy {
|
|
7
|
+
routesToReturn;
|
|
8
|
+
name = 'mock';
|
|
9
|
+
lastInflightContext;
|
|
10
|
+
constructor(routesToReturn) {
|
|
11
|
+
this.routesToReturn = routesToReturn;
|
|
12
|
+
}
|
|
13
|
+
getRebalancingRoutes(_rawBalances, inflightContext) {
|
|
14
|
+
this.lastInflightContext = inflightContext;
|
|
15
|
+
return this.routesToReturn;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
describe('CompositeStrategy', () => {
|
|
19
|
+
let chain1;
|
|
20
|
+
let chain2;
|
|
21
|
+
let chain3;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
chain1 = 'chain1';
|
|
24
|
+
chain2 = 'chain2';
|
|
25
|
+
chain3 = 'chain3';
|
|
26
|
+
});
|
|
27
|
+
describe('constructor', () => {
|
|
28
|
+
it('should throw an error when less than 2 strategies are provided', () => {
|
|
29
|
+
const mockStrategy = new MockStrategy([]);
|
|
30
|
+
expect(() => new CompositeStrategy([mockStrategy], testLogger)).to.throw('CompositeStrategy requires at least 2 sub-strategies');
|
|
31
|
+
});
|
|
32
|
+
it('should throw an error when no strategies are provided', () => {
|
|
33
|
+
expect(() => new CompositeStrategy([], testLogger)).to.throw('CompositeStrategy requires at least 2 sub-strategies');
|
|
34
|
+
});
|
|
35
|
+
it('should create a strategy with 2+ sub-strategies', () => {
|
|
36
|
+
const strategy1 = new MockStrategy([]);
|
|
37
|
+
const strategy2 = new MockStrategy([]);
|
|
38
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
39
|
+
expect(composite).to.be.instanceOf(CompositeStrategy);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('getRebalancingRoutes', () => {
|
|
43
|
+
it('should concatenate routes from all sub-strategies', () => {
|
|
44
|
+
const route1 = {
|
|
45
|
+
origin: chain1,
|
|
46
|
+
destination: chain2,
|
|
47
|
+
amount: 1000n,
|
|
48
|
+
bridge: TEST_BRIDGE,
|
|
49
|
+
};
|
|
50
|
+
const route2 = {
|
|
51
|
+
origin: chain2,
|
|
52
|
+
destination: chain3,
|
|
53
|
+
amount: 2000n,
|
|
54
|
+
bridge: TEST_BRIDGE,
|
|
55
|
+
};
|
|
56
|
+
const strategy1 = new MockStrategy([route1]);
|
|
57
|
+
const strategy2 = new MockStrategy([route2]);
|
|
58
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
59
|
+
const rawBalances = {
|
|
60
|
+
[chain1]: 5000n,
|
|
61
|
+
[chain2]: 10000n,
|
|
62
|
+
[chain3]: 3000n,
|
|
63
|
+
};
|
|
64
|
+
const routes = composite.getRebalancingRoutes(rawBalances);
|
|
65
|
+
expect(routes).to.have.lengthOf(2);
|
|
66
|
+
expect(routes[0]).to.deep.equal(route1);
|
|
67
|
+
expect(routes[1]).to.deep.equal(route2);
|
|
68
|
+
});
|
|
69
|
+
it('should pass routes from earlier strategies as proposedRebalances to later strategies', () => {
|
|
70
|
+
const route1 = {
|
|
71
|
+
origin: chain1,
|
|
72
|
+
destination: chain2,
|
|
73
|
+
amount: 1000n,
|
|
74
|
+
bridge: TEST_BRIDGE,
|
|
75
|
+
};
|
|
76
|
+
const strategy1 = new MockStrategy([route1]);
|
|
77
|
+
const strategy2 = new MockStrategy([]);
|
|
78
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
79
|
+
const rawBalances = {
|
|
80
|
+
[chain1]: 5000n,
|
|
81
|
+
[chain2]: 10000n,
|
|
82
|
+
};
|
|
83
|
+
composite.getRebalancingRoutes(rawBalances);
|
|
84
|
+
// Strategy 1 should receive empty proposedRebalances (none from earlier strategies)
|
|
85
|
+
expect(strategy1.lastInflightContext?.proposedRebalances).to.deep.equal([]);
|
|
86
|
+
// Strategy 2 should receive route1 as proposedRebalances (from earlier strategy)
|
|
87
|
+
expect(strategy2.lastInflightContext?.proposedRebalances).to.have.lengthOf(1);
|
|
88
|
+
expect(strategy2.lastInflightContext?.proposedRebalances?.[0]).to.deep.equal(route1);
|
|
89
|
+
});
|
|
90
|
+
it('should accumulate routes across multiple strategies as proposedRebalances', () => {
|
|
91
|
+
const route1 = {
|
|
92
|
+
origin: chain1,
|
|
93
|
+
destination: chain2,
|
|
94
|
+
amount: 1000n,
|
|
95
|
+
bridge: TEST_BRIDGE,
|
|
96
|
+
};
|
|
97
|
+
const route2 = {
|
|
98
|
+
origin: chain2,
|
|
99
|
+
destination: chain3,
|
|
100
|
+
amount: 2000n,
|
|
101
|
+
bridge: TEST_BRIDGE,
|
|
102
|
+
};
|
|
103
|
+
const route3 = {
|
|
104
|
+
origin: chain3,
|
|
105
|
+
destination: chain1,
|
|
106
|
+
amount: 3000n,
|
|
107
|
+
bridge: TEST_BRIDGE,
|
|
108
|
+
};
|
|
109
|
+
const strategy1 = new MockStrategy([route1]);
|
|
110
|
+
const strategy2 = new MockStrategy([route2]);
|
|
111
|
+
const strategy3 = new MockStrategy([route3]);
|
|
112
|
+
const composite = new CompositeStrategy([strategy1, strategy2, strategy3], testLogger);
|
|
113
|
+
const rawBalances = {
|
|
114
|
+
[chain1]: 5000n,
|
|
115
|
+
[chain2]: 10000n,
|
|
116
|
+
[chain3]: 3000n,
|
|
117
|
+
};
|
|
118
|
+
composite.getRebalancingRoutes(rawBalances);
|
|
119
|
+
// Strategy 1: empty proposedRebalances (no earlier strategies)
|
|
120
|
+
expect(strategy1.lastInflightContext?.proposedRebalances).to.deep.equal([]);
|
|
121
|
+
// Strategy 2: receives route1 as proposedRebalances
|
|
122
|
+
expect(strategy2.lastInflightContext?.proposedRebalances).to.have.lengthOf(1);
|
|
123
|
+
// Strategy 3: receives route1 + route2 as proposedRebalances
|
|
124
|
+
expect(strategy3.lastInflightContext?.proposedRebalances).to.have.lengthOf(2);
|
|
125
|
+
expect(strategy3.lastInflightContext?.proposedRebalances?.[0]).to.deep.equal(route1);
|
|
126
|
+
expect(strategy3.lastInflightContext?.proposedRebalances?.[1]).to.deep.equal(route2);
|
|
127
|
+
});
|
|
128
|
+
it('should preserve original pendingRebalances and use proposedRebalances for new routes', () => {
|
|
129
|
+
const originalPendingRebalance = {
|
|
130
|
+
origin: chain3,
|
|
131
|
+
destination: chain1,
|
|
132
|
+
amount: 500n,
|
|
133
|
+
bridge: TEST_BRIDGE,
|
|
134
|
+
};
|
|
135
|
+
const route1 = {
|
|
136
|
+
origin: chain1,
|
|
137
|
+
destination: chain2,
|
|
138
|
+
amount: 1000n,
|
|
139
|
+
bridge: TEST_BRIDGE,
|
|
140
|
+
};
|
|
141
|
+
const strategy1 = new MockStrategy([route1]);
|
|
142
|
+
const strategy2 = new MockStrategy([]);
|
|
143
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
144
|
+
const rawBalances = {
|
|
145
|
+
[chain1]: 5000n,
|
|
146
|
+
[chain2]: 10000n,
|
|
147
|
+
[chain3]: 3000n,
|
|
148
|
+
};
|
|
149
|
+
const inflightContext = {
|
|
150
|
+
pendingTransfers: [],
|
|
151
|
+
pendingRebalances: [originalPendingRebalance],
|
|
152
|
+
};
|
|
153
|
+
composite.getRebalancingRoutes(rawBalances, inflightContext);
|
|
154
|
+
// Both strategies should receive the SAME original pendingRebalances (inflight intents)
|
|
155
|
+
expect(strategy1.lastInflightContext?.pendingRebalances).to.have.lengthOf(1);
|
|
156
|
+
expect(strategy1.lastInflightContext?.pendingRebalances[0]).to.deep.equal(originalPendingRebalance);
|
|
157
|
+
expect(strategy2.lastInflightContext?.pendingRebalances).to.have.lengthOf(1);
|
|
158
|
+
expect(strategy2.lastInflightContext?.pendingRebalances[0]).to.deep.equal(originalPendingRebalance);
|
|
159
|
+
// Strategy 1: empty proposedRebalances (no earlier strategies)
|
|
160
|
+
expect(strategy1.lastInflightContext?.proposedRebalances).to.deep.equal([]);
|
|
161
|
+
// Strategy 2: receives route1 as proposedRebalances (from earlier strategy)
|
|
162
|
+
expect(strategy2.lastInflightContext?.proposedRebalances).to.have.lengthOf(1);
|
|
163
|
+
expect(strategy2.lastInflightContext?.proposedRebalances?.[0]).to.deep.equal(route1);
|
|
164
|
+
});
|
|
165
|
+
it('should preserve pendingTransfers for all strategies', () => {
|
|
166
|
+
const pendingTransfer = {
|
|
167
|
+
origin: chain1,
|
|
168
|
+
destination: chain2,
|
|
169
|
+
amount: 500n,
|
|
170
|
+
};
|
|
171
|
+
const strategy1 = new MockStrategy([]);
|
|
172
|
+
const strategy2 = new MockStrategy([]);
|
|
173
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
174
|
+
const rawBalances = {
|
|
175
|
+
[chain1]: 5000n,
|
|
176
|
+
[chain2]: 10000n,
|
|
177
|
+
};
|
|
178
|
+
const inflightContext = {
|
|
179
|
+
pendingTransfers: [pendingTransfer],
|
|
180
|
+
pendingRebalances: [],
|
|
181
|
+
};
|
|
182
|
+
composite.getRebalancingRoutes(rawBalances, inflightContext);
|
|
183
|
+
// Both strategies should receive the same pendingTransfers
|
|
184
|
+
expect(strategy1.lastInflightContext?.pendingTransfers).to.deep.equal([
|
|
185
|
+
pendingTransfer,
|
|
186
|
+
]);
|
|
187
|
+
expect(strategy2.lastInflightContext?.pendingTransfers).to.deep.equal([
|
|
188
|
+
pendingTransfer,
|
|
189
|
+
]);
|
|
190
|
+
});
|
|
191
|
+
it('should maintain route order (first strategy routes come first)', () => {
|
|
192
|
+
const route1a = {
|
|
193
|
+
origin: chain1,
|
|
194
|
+
destination: chain2,
|
|
195
|
+
amount: 1000n,
|
|
196
|
+
bridge: TEST_BRIDGE,
|
|
197
|
+
};
|
|
198
|
+
const route1b = {
|
|
199
|
+
origin: chain1,
|
|
200
|
+
destination: chain3,
|
|
201
|
+
amount: 1500n,
|
|
202
|
+
bridge: TEST_BRIDGE,
|
|
203
|
+
};
|
|
204
|
+
const route2a = {
|
|
205
|
+
origin: chain2,
|
|
206
|
+
destination: chain3,
|
|
207
|
+
amount: 2000n,
|
|
208
|
+
bridge: TEST_BRIDGE,
|
|
209
|
+
};
|
|
210
|
+
const strategy1 = new MockStrategy([route1a, route1b]);
|
|
211
|
+
const strategy2 = new MockStrategy([route2a]);
|
|
212
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
213
|
+
const rawBalances = {
|
|
214
|
+
[chain1]: 5000n,
|
|
215
|
+
[chain2]: 10000n,
|
|
216
|
+
[chain3]: 3000n,
|
|
217
|
+
};
|
|
218
|
+
const routes = composite.getRebalancingRoutes(rawBalances);
|
|
219
|
+
expect(routes).to.have.lengthOf(3);
|
|
220
|
+
expect(routes[0]).to.deep.equal(route1a);
|
|
221
|
+
expect(routes[1]).to.deep.equal(route1b);
|
|
222
|
+
expect(routes[2]).to.deep.equal(route2a);
|
|
223
|
+
});
|
|
224
|
+
it('should handle strategies that return no routes', () => {
|
|
225
|
+
const route2 = {
|
|
226
|
+
origin: chain2,
|
|
227
|
+
destination: chain3,
|
|
228
|
+
amount: 2000n,
|
|
229
|
+
bridge: TEST_BRIDGE,
|
|
230
|
+
};
|
|
231
|
+
const strategy1 = new MockStrategy([]);
|
|
232
|
+
const strategy2 = new MockStrategy([route2]);
|
|
233
|
+
const strategy3 = new MockStrategy([]);
|
|
234
|
+
const composite = new CompositeStrategy([strategy1, strategy2, strategy3], testLogger);
|
|
235
|
+
const rawBalances = {
|
|
236
|
+
[chain1]: 5000n,
|
|
237
|
+
[chain2]: 10000n,
|
|
238
|
+
[chain3]: 3000n,
|
|
239
|
+
};
|
|
240
|
+
const routes = composite.getRebalancingRoutes(rawBalances);
|
|
241
|
+
expect(routes).to.have.lengthOf(1);
|
|
242
|
+
expect(routes[0]).to.deep.equal(route2);
|
|
243
|
+
});
|
|
244
|
+
it('should handle undefined inflightContext', () => {
|
|
245
|
+
const route1 = {
|
|
246
|
+
origin: chain1,
|
|
247
|
+
destination: chain2,
|
|
248
|
+
amount: 1000n,
|
|
249
|
+
bridge: TEST_BRIDGE,
|
|
250
|
+
};
|
|
251
|
+
const strategy1 = new MockStrategy([route1]);
|
|
252
|
+
const strategy2 = new MockStrategy([]);
|
|
253
|
+
const composite = new CompositeStrategy([strategy1, strategy2], testLogger);
|
|
254
|
+
const rawBalances = {
|
|
255
|
+
[chain1]: 5000n,
|
|
256
|
+
[chain2]: 10000n,
|
|
257
|
+
};
|
|
258
|
+
const routes = composite.getRebalancingRoutes(rawBalances, undefined);
|
|
259
|
+
expect(routes).to.have.lengthOf(1);
|
|
260
|
+
expect(strategy1.lastInflightContext?.pendingTransfers).to.deep.equal([]);
|
|
261
|
+
expect(strategy1.lastInflightContext?.pendingRebalances).to.deep.equal([]);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
//# sourceMappingURL=CompositeStrategy.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompositeStrategy.test.js","sourceRoot":"","sources":["../../src/strategy/CompositeStrategy.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import { type Logger } from 'pino';
|
|
2
2
|
import { type ChainMap, type Token } from '@hyperlane-xyz/sdk';
|
|
3
|
-
import { type MinAmountStrategyConfig } from '../config/types.js';
|
|
4
|
-
import type { RawBalances } from '../interfaces/IStrategy.js';
|
|
3
|
+
import { type MinAmountStrategyConfig, RebalancerStrategyOptions } from '../config/types.js';
|
|
4
|
+
import type { RawBalances, Route, StrategyRoute } from '../interfaces/IStrategy.js';
|
|
5
5
|
import { type Metrics } from '../metrics/Metrics.js';
|
|
6
|
+
import type { BridgeConfigWithOverride } from '../utils/bridgeUtils.js';
|
|
6
7
|
import { BaseStrategy, type Delta } from './BaseStrategy.js';
|
|
7
8
|
/**
|
|
8
9
|
* Strategy implementation that rebalance based on minimum amounts
|
|
9
10
|
* It ensures each chain has at least the specified minimum amount
|
|
10
11
|
*/
|
|
11
12
|
export declare class MinAmountStrategy extends BaseStrategy {
|
|
12
|
-
|
|
13
|
+
readonly name = RebalancerStrategyOptions.MinAmount;
|
|
13
14
|
private readonly config;
|
|
14
15
|
protected readonly logger: Logger;
|
|
15
|
-
constructor(config: MinAmountStrategyConfig, tokensByChainName: ChainMap<Token>, initialTotalCollateral: bigint, logger: Logger, metrics?: Metrics);
|
|
16
|
+
constructor(config: MinAmountStrategyConfig, tokensByChainName: ChainMap<Token>, initialTotalCollateral: bigint, logger: Logger, bridgeConfigs: ChainMap<BridgeConfigWithOverride>, metrics?: Metrics);
|
|
16
17
|
/**
|
|
17
18
|
* Gets balances categorized by surplus and deficit based on minimum amounts and targets
|
|
18
19
|
* - For absolute values: Uses exact token amounts
|
|
19
20
|
* - For relative values: Uses percentages of total balance across all chains
|
|
21
|
+
*
|
|
22
|
+
* Simulates both types of rebalances before calculating surpluses/deficits:
|
|
23
|
+
* - pendingRebalances: in-flight intents (origin tx confirmed, add to destination only)
|
|
24
|
+
* - proposedRebalances: routes from earlier strategies (subtract from origin AND add to destination)
|
|
25
|
+
*
|
|
26
|
+
* This prevents over-rebalancing when multiple strategies run in sequence.
|
|
20
27
|
*/
|
|
21
|
-
protected getCategorizedBalances(rawBalances: RawBalances): {
|
|
28
|
+
protected getCategorizedBalances(rawBalances: RawBalances, pendingRebalances?: Route[], proposedRebalances?: StrategyRoute[]): {
|
|
22
29
|
surpluses: Delta[];
|
|
23
30
|
deficits: Delta[];
|
|
24
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MinAmountStrategy.d.ts","sourceRoot":"","sources":["../../src/strategy/MinAmountStrategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG/D,OAAO,EACL,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"MinAmountStrategy.d.ts","sourceRoot":"","sources":["../../src/strategy/MinAmountStrategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG/D,OAAO,EACL,KAAK,uBAAuB,EAE5B,yBAAyB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,WAAW,EACX,KAAK,EACL,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE7D;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,QAAQ,CAAC,IAAI,uCAAuC;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGhC,MAAM,EAAE,uBAAuB,EAC/B,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,EAClC,sBAAsB,EAAE,MAAM,EAC9B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,QAAQ,CAAC,wBAAwB,CAAC,EACjD,OAAO,CAAC,EAAE,OAAO;IAqCnB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,sBAAsB,CAC9B,WAAW,EAAE,WAAW,EACxB,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;IAgED,SAAS,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK;IAUvD,OAAO,CAAC,eAAe;CAkCxB"}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { BigNumber } from 'bignumber.js';
|
|
2
2
|
import { fromWei, toWei } from '@hyperlane-xyz/utils';
|
|
3
|
-
import { RebalancerMinAmountType, } from '../config/types.js';
|
|
3
|
+
import { RebalancerMinAmountType, RebalancerStrategyOptions, } from '../config/types.js';
|
|
4
4
|
import { BaseStrategy } from './BaseStrategy.js';
|
|
5
5
|
/**
|
|
6
6
|
* Strategy implementation that rebalance based on minimum amounts
|
|
7
7
|
* It ensures each chain has at least the specified minimum amount
|
|
8
8
|
*/
|
|
9
9
|
export class MinAmountStrategy extends BaseStrategy {
|
|
10
|
-
|
|
10
|
+
name = RebalancerStrategyOptions.MinAmount;
|
|
11
11
|
config = {};
|
|
12
12
|
logger;
|
|
13
|
-
constructor(config, tokensByChainName, initialTotalCollateral, logger, metrics) {
|
|
13
|
+
constructor(config, tokensByChainName, initialTotalCollateral, logger, bridgeConfigs, metrics) {
|
|
14
14
|
const chains = Object.keys(config);
|
|
15
15
|
const log = logger.child({ class: MinAmountStrategy.name });
|
|
16
|
-
super(chains, log, metrics);
|
|
17
|
-
this.tokensByChainName = tokensByChainName;
|
|
16
|
+
super(chains, log, bridgeConfigs, metrics, tokensByChainName);
|
|
18
17
|
this.logger = log;
|
|
19
18
|
const minAmountType = config[chains[0]].minAmount.type;
|
|
20
19
|
this.validateAmounts(initialTotalCollateral, minAmountType, config);
|
|
@@ -38,25 +37,35 @@ export class MinAmountStrategy extends BaseStrategy {
|
|
|
38
37
|
* Gets balances categorized by surplus and deficit based on minimum amounts and targets
|
|
39
38
|
* - For absolute values: Uses exact token amounts
|
|
40
39
|
* - For relative values: Uses percentages of total balance across all chains
|
|
40
|
+
*
|
|
41
|
+
* Simulates both types of rebalances before calculating surpluses/deficits:
|
|
42
|
+
* - pendingRebalances: in-flight intents (origin tx confirmed, add to destination only)
|
|
43
|
+
* - proposedRebalances: routes from earlier strategies (subtract from origin AND add to destination)
|
|
44
|
+
*
|
|
45
|
+
* This prevents over-rebalancing when multiple strategies run in sequence.
|
|
41
46
|
*/
|
|
42
|
-
getCategorizedBalances(rawBalances) {
|
|
43
|
-
|
|
47
|
+
getCategorizedBalances(rawBalances, pendingRebalances, proposedRebalances) {
|
|
48
|
+
// Step 1: Simulate pending rebalances (in-flight, origin already deducted on-chain)
|
|
49
|
+
let simulatedBalances = this.simulatePendingRebalances(rawBalances, pendingRebalances ?? []);
|
|
50
|
+
// Step 2: Simulate proposed rebalances (from earlier strategies, not yet executed)
|
|
51
|
+
simulatedBalances = this.simulateProposedRebalances(simulatedBalances, proposedRebalances ?? []);
|
|
52
|
+
const totalCollateral = this.chains.reduce((sum, chain) => sum + simulatedBalances[chain], 0n);
|
|
44
53
|
return this.chains.reduce((acc, chain) => {
|
|
45
|
-
const
|
|
46
|
-
const balance =
|
|
54
|
+
const chainConfig = this.config[chain];
|
|
55
|
+
const balance = simulatedBalances[chain];
|
|
47
56
|
let minAmount;
|
|
48
57
|
let targetAmount;
|
|
49
|
-
if (
|
|
58
|
+
if (chainConfig.minAmount.type === RebalancerMinAmountType.Absolute) {
|
|
50
59
|
const token = this.getTokenByChainName(chain);
|
|
51
|
-
minAmount = BigInt(toWei(
|
|
52
|
-
targetAmount = BigInt(toWei(
|
|
60
|
+
minAmount = BigInt(toWei(chainConfig.minAmount.min, token.decimals));
|
|
61
|
+
targetAmount = BigInt(toWei(chainConfig.minAmount.target, token.decimals));
|
|
53
62
|
}
|
|
54
63
|
else {
|
|
55
64
|
minAmount = BigInt(BigNumber(totalCollateral.toString())
|
|
56
|
-
.times(
|
|
65
|
+
.times(chainConfig.minAmount.min)
|
|
57
66
|
.toFixed(0, BigNumber.ROUND_FLOOR));
|
|
58
67
|
targetAmount = BigInt(BigNumber(totalCollateral.toString())
|
|
59
|
-
.times(
|
|
68
|
+
.times(chainConfig.minAmount.target)
|
|
60
69
|
.toFixed(0, BigNumber.ROUND_FLOOR));
|
|
61
70
|
}
|
|
62
71
|
// If balance is less than minAmount, it has a deficit
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MinAmountStrategy.js","sourceRoot":"","sources":["../../src/strategy/MinAmountStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAEL,uBAAuB,
|
|
1
|
+
{"version":3,"file":"MinAmountStrategy.js","sourceRoot":"","sources":["../../src/strategy/MinAmountStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAEL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAS5B,OAAO,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AAE7D;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACxC,IAAI,GAAG,yBAAyB,CAAC,SAAS,CAAC;IACnC,MAAM,GAA4B,EAAE,CAAC;IACnC,MAAM,CAAS;IAElC,YACE,MAA+B,EAC/B,iBAAkC,EAClC,sBAA8B,EAC9B,MAAc,EACd,aAAiD,EACjD,OAAiB;QAEjB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QAElB,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;QACvD,IAAI,CAAC,eAAe,CAAC,sBAAsB,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAEpE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC;YAEhD,0BAA0B;YAC1B,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CACb,WAAW,MAAM,2CAA2C,GAAG,eAAe,KAAK,EAAE,CACtF,CAAC;YACJ,CAAC;YAED,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,mBAAmB,GAAG,kCAAkC,KAAK,EAAE,CAChE,CAAC;YACJ,CAAC;YAED,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,kCAAkC,KAAK,EAAE,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;;;;OAUG;IACO,sBAAsB,CAC9B,WAAwB,EACxB,iBAA2B,EAC3B,kBAAoC;QAKpC,oFAAoF;QACpF,IAAI,iBAAiB,GAAG,IAAI,CAAC,yBAAyB,CACpD,WAAW,EACX,iBAAiB,IAAI,EAAE,CACxB,CAAC;QAEF,mFAAmF;QACnF,iBAAiB,GAAG,IAAI,CAAC,0BAA0B,CACjD,iBAAiB,EACjB,kBAAkB,IAAI,EAAE,CACzB,CAAC;QACF,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CACxC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAC9C,EAAE,CACH,CAAC;QAEF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CACvB,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACb,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,SAAiB,CAAC;YACtB,IAAI,YAAoB,CAAC;YAEzB,IAAI,WAAW,CAAC,SAAS,CAAC,IAAI,KAAK,uBAAuB,CAAC,QAAQ,EAAE,CAAC;gBACpE,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAE9C,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACrE,YAAY,GAAG,MAAM,CACnB,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CACpD,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,MAAM,CAChB,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;qBAClC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC;qBAChC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CACrC,CAAC;gBACF,YAAY,GAAG,MAAM,CACnB,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;qBAClC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;qBACnC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CACrC,CAAC;YACJ,CAAC;YAED,sDAAsD;YACtD,IAAI,OAAO,GAAG,SAAS,EAAE,CAAC;gBACxB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,EAAE,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,6DAA6D;gBAC7D,MAAM,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;gBACpC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;oBACjB,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YAED,OAAO,GAAG,CAAC;QACb,CAAC,EACD;YACE,SAAS,EAAE,EAAa;YACxB,QAAQ,EAAE,EAAa;SACxB,CACF,CAAC;IACJ,CAAC;IAES,mBAAmB,CAAC,SAAiB;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAkB,CAAC,SAAS,CAAC,CAAC;QAEjD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,SAAS,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,eAAe,CACrB,eAAuB,EACvB,aAAsC,EACtC,MAAgC;QAEhC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC;QAEvB,IAAI,aAAa,KAAK,uBAAuB,CAAC,QAAQ,EAAE,CAAC;YACvD,IAAI,YAAY,GAAG,EAAE,CAAC;YACtB,IAAI,QAAQ,GAAW,CAAC,CAAC;YAEzB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;gBAClD,kDAAkD;gBAClD,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;gBAE1B,YAAY,IAAI,MAAM,CACpB,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAC1D,CAAC;YACJ,CAAC;YAED,IAAI,YAAY,GAAG,eAAe,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CACb,6CAA6C,OAAO,CAClD,YAAY,CAAC,QAAQ,EAAE,EACvB,QAAQ,CACT,yCAAyC,OAAO,CAC/C,eAAe,CAAC,QAAQ,EAAE,EAC1B,QAAQ,CACT,GAAG,CACL,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|