@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
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { MultiProvider } from '@hyperlane-xyz/sdk';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
InflightContext,
|
|
5
|
+
RouteWithContext,
|
|
6
|
+
} from '../interfaces/IStrategy.js';
|
|
4
7
|
|
|
5
8
|
import type { IActionTracker } from './IActionTracker.js';
|
|
6
9
|
|
|
@@ -22,14 +25,44 @@ export class InflightContextAdapter {
|
|
|
22
25
|
const intents = await this.actionTracker.getActiveRebalanceIntents();
|
|
23
26
|
const transfers = await this.actionTracker.getInProgressTransfers();
|
|
24
27
|
|
|
25
|
-
const pendingRebalances =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
const pendingRebalances: RouteWithContext[] = await Promise.all(
|
|
29
|
+
intents.map(async (intent) => {
|
|
30
|
+
let deliveredAmount = 0n;
|
|
31
|
+
let awaitingDeliveryAmount = 0n;
|
|
32
|
+
|
|
33
|
+
// For inventory intents, compute delivered and awaiting amounts from actions
|
|
34
|
+
if (intent.executionMethod === 'inventory') {
|
|
35
|
+
const actions = await this.actionTracker.getActionsForIntent(
|
|
36
|
+
intent.id,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Sum of complete inventory_deposit actions (message delivered)
|
|
40
|
+
deliveredAmount = actions
|
|
41
|
+
.filter(
|
|
42
|
+
(a) => a.type === 'inventory_deposit' && a.status === 'complete',
|
|
43
|
+
)
|
|
44
|
+
.reduce((sum, a) => sum + a.amount, 0n);
|
|
45
|
+
|
|
46
|
+
// Sum of in_progress inventory_deposit actions (tx confirmed, message pending)
|
|
47
|
+
awaitingDeliveryAmount = actions
|
|
48
|
+
.filter(
|
|
49
|
+
(a) =>
|
|
50
|
+
a.type === 'inventory_deposit' && a.status === 'in_progress',
|
|
51
|
+
)
|
|
52
|
+
.reduce((sum, a) => sum + a.amount, 0n);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
origin: this.multiProvider.getChainName(intent.origin),
|
|
57
|
+
destination: this.multiProvider.getChainName(intent.destination),
|
|
58
|
+
amount: intent.amount,
|
|
59
|
+
deliveredAmount,
|
|
60
|
+
awaitingDeliveryAmount,
|
|
61
|
+
executionMethod: intent.executionMethod,
|
|
62
|
+
bridge: intent.bridge,
|
|
63
|
+
};
|
|
64
|
+
}),
|
|
65
|
+
);
|
|
33
66
|
|
|
34
67
|
const pendingTransfers = transfers.map((transfer) => ({
|
|
35
68
|
origin: this.multiProvider.getChainName(transfer.origin),
|
package/src/tracking/types.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Address, Domain } from '@hyperlane-xyz/utils';
|
|
2
2
|
|
|
3
|
+
import type { ExternalBridgeType } from '../config/types.js';
|
|
4
|
+
|
|
3
5
|
import type { IStore } from './store/IStore.js';
|
|
4
6
|
|
|
5
7
|
// === Base Interfaces ===
|
|
@@ -35,6 +37,26 @@ export type RebalanceIntentStatus =
|
|
|
35
37
|
| 'failed';
|
|
36
38
|
export type RebalanceActionStatus = 'in_progress' | 'complete' | 'failed';
|
|
37
39
|
|
|
40
|
+
// === Execution Types ===
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Execution method for rebalancing:
|
|
44
|
+
* - `movable_collateral`: Uses MovableCollateralRouter.rebalance() on-chain
|
|
45
|
+
* - `inventory`: Uses external bridges + transferRemote
|
|
46
|
+
*/
|
|
47
|
+
export type ExecutionMethod = 'movable_collateral' | 'inventory';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Type of rebalance action:
|
|
51
|
+
* - `rebalance_message`: Standard movable collateral rebalance (Hyperlane message)
|
|
52
|
+
* - `inventory_movement`: External bridge transfer (e.g., LiFi) to move inventory
|
|
53
|
+
* - `inventory_deposit`: transferRemote to deposit inventory as collateral
|
|
54
|
+
*/
|
|
55
|
+
export type ActionType =
|
|
56
|
+
| 'rebalance_message'
|
|
57
|
+
| 'inventory_movement'
|
|
58
|
+
| 'inventory_deposit';
|
|
59
|
+
|
|
38
60
|
// === Entity Types ===
|
|
39
61
|
|
|
40
62
|
export interface Transfer extends TrackedActionBase {
|
|
@@ -46,17 +68,22 @@ export interface Transfer extends TrackedActionBase {
|
|
|
46
68
|
|
|
47
69
|
export interface RebalanceIntent extends TrackedActionBase {
|
|
48
70
|
status: RebalanceIntentStatus;
|
|
49
|
-
fulfilledAmount: bigint;
|
|
50
71
|
bridge?: Address; // Optional - bridge contract used (missing for recovered intents)
|
|
51
72
|
priority?: number; // Optional - missing for recovered intents
|
|
52
73
|
strategyType?: string; // Optional - missing for recovered intents
|
|
74
|
+
executionMethod?: ExecutionMethod; // Optional - defaults to movable_collateral
|
|
75
|
+
externalBridge?: ExternalBridgeType; // Optional - external bridge type (e.g., LiFi)
|
|
53
76
|
}
|
|
54
77
|
|
|
55
78
|
export interface RebalanceAction extends TrackedActionBase {
|
|
56
79
|
status: RebalanceActionStatus;
|
|
80
|
+
type: ActionType; // Type of action (rebalance_message, inventory_movement, inventory_deposit)
|
|
57
81
|
intentId: string; // Links to parent RebalanceIntent
|
|
58
|
-
messageId
|
|
82
|
+
messageId?: string; // Hyperlane message ID (required for rebalance_message, inventory_deposit)
|
|
59
83
|
txHash?: string; // Origin transaction hash
|
|
84
|
+
// Fields for inventory_movement (external bridge)
|
|
85
|
+
externalBridgeTransferId?: string; // External bridge transfer ID (e.g., LiFi transfer ID)
|
|
86
|
+
externalBridgeId?: ExternalBridgeType; // External bridge identifier (e.g., 'lifi')
|
|
60
87
|
}
|
|
61
88
|
|
|
62
89
|
// === Type Aliases for Stores ===
|
|
@@ -70,3 +97,19 @@ export type IRebalanceActionStore = IStore<
|
|
|
70
97
|
RebalanceAction,
|
|
71
98
|
RebalanceActionStatus
|
|
72
99
|
>;
|
|
100
|
+
|
|
101
|
+
// === Derived Types ===
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Represents an inventory intent that has been partially fulfilled
|
|
105
|
+
* and can continue execution. Values are derived from action states.
|
|
106
|
+
*/
|
|
107
|
+
export interface PartialInventoryIntent {
|
|
108
|
+
intent: RebalanceIntent;
|
|
109
|
+
/** Sum of complete inventory_deposit action amounts */
|
|
110
|
+
completedAmount: bigint;
|
|
111
|
+
/** Amount remaining to fulfill (0n when final deposit is fully in-flight). Formula: intent.amount - completedAmount - inflightAmount */
|
|
112
|
+
remaining: bigint;
|
|
113
|
+
/** True when intent has in_progress inventory_deposit actions (not safe to continue, but still active) */
|
|
114
|
+
hasInflightDeposit: boolean;
|
|
115
|
+
}
|
|
@@ -9,14 +9,15 @@ export type InflightRebalanceQueryParams = {
|
|
|
9
9
|
|
|
10
10
|
export type UserTransferQueryParams = {
|
|
11
11
|
routersByDomain: Record<number, string>; // Domain ID → router address (derive routers and domains from this)
|
|
12
|
-
|
|
12
|
+
excludeTxSenders: string[]; // Addresses to exclude (rebalancer + inventory signer)
|
|
13
13
|
limit?: number;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export type RebalanceActionQueryParams = {
|
|
17
17
|
bridges: string[]; // Bridge contract addresses
|
|
18
18
|
routersByDomain: Record<number, string>; // Domain ID → router address (derive routers and domains from this)
|
|
19
|
-
rebalancerAddress: string; //
|
|
19
|
+
rebalancerAddress: string; // Include rebalancer's txs
|
|
20
|
+
inventorySignerAddress?: string; // Optional: also include inventory signer's txs (for inventory_deposit actions)
|
|
20
21
|
limit?: number;
|
|
21
22
|
};
|
|
22
23
|
|
|
@@ -31,6 +32,7 @@ export type ExplorerMessage = {
|
|
|
31
32
|
origin_tx_recipient: string;
|
|
32
33
|
is_delivered: boolean;
|
|
33
34
|
message_body: string;
|
|
35
|
+
send_occurred_at: string | null;
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
export interface IExplorerClient {
|
|
@@ -71,6 +73,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
71
73
|
origin_tx_recipient: normalizeHex(msg.origin_tx_recipient),
|
|
72
74
|
is_delivered: msg.is_delivered,
|
|
73
75
|
message_body: normalizeHex(msg.message_body),
|
|
76
|
+
send_occurred_at: msg.send_occurred_at ?? null,
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -191,7 +194,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
191
194
|
params: UserTransferQueryParams,
|
|
192
195
|
logger: Logger,
|
|
193
196
|
): Promise<ExplorerMessage[]> {
|
|
194
|
-
const { routersByDomain,
|
|
197
|
+
const { routersByDomain, excludeTxSenders, limit = 100 } = params;
|
|
195
198
|
|
|
196
199
|
// Derive routers and domains from routersByDomain
|
|
197
200
|
const routers = Object.values(routersByDomain);
|
|
@@ -202,7 +205,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
202
205
|
recipients: routers.map((a) => this.toBytea(a)),
|
|
203
206
|
originDomains: domains,
|
|
204
207
|
destDomains: domains,
|
|
205
|
-
|
|
208
|
+
excludeTxSenders: excludeTxSenders.map((a) => this.toBytea(a)),
|
|
206
209
|
limit,
|
|
207
210
|
};
|
|
208
211
|
|
|
@@ -214,7 +217,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
214
217
|
$recipients: [bytea!],
|
|
215
218
|
$originDomains: [Int!],
|
|
216
219
|
$destDomains: [Int!],
|
|
217
|
-
$
|
|
220
|
+
$excludeTxSenders: [bytea!],
|
|
218
221
|
$limit: Int = 100
|
|
219
222
|
) {
|
|
220
223
|
message_view(
|
|
@@ -225,7 +228,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
225
228
|
{ recipient: { _in: $recipients } },
|
|
226
229
|
{ origin_domain_id: { _in: $originDomains } },
|
|
227
230
|
{ destination_domain_id: { _in: $destDomains } },
|
|
228
|
-
{ origin_tx_sender: {
|
|
231
|
+
{ origin_tx_sender: { _nin: $excludeTxSenders } }
|
|
229
232
|
]
|
|
230
233
|
}
|
|
231
234
|
order_by: { origin_tx_id: desc }
|
|
@@ -241,6 +244,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
241
244
|
origin_tx_recipient
|
|
242
245
|
is_delivered
|
|
243
246
|
message_body
|
|
247
|
+
send_occurred_at
|
|
244
248
|
}
|
|
245
249
|
}`;
|
|
246
250
|
|
|
@@ -284,19 +288,31 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
284
288
|
params: RebalanceActionQueryParams,
|
|
285
289
|
logger: Logger,
|
|
286
290
|
): Promise<ExplorerMessage[]> {
|
|
287
|
-
const {
|
|
291
|
+
const {
|
|
292
|
+
bridges,
|
|
293
|
+
routersByDomain,
|
|
294
|
+
rebalancerAddress,
|
|
295
|
+
inventorySignerAddress,
|
|
296
|
+
limit = 100,
|
|
297
|
+
} = params;
|
|
288
298
|
|
|
289
299
|
// Derive routers and domains from routersByDomain
|
|
290
300
|
const routers = Object.values(routersByDomain);
|
|
291
301
|
const domains = Object.keys(routersByDomain).map(Number);
|
|
292
302
|
|
|
303
|
+
// Build list of tx senders to include (rebalancer + optional inventory signer)
|
|
304
|
+
const txSenders = [this.toBytea(rebalancerAddress)];
|
|
305
|
+
if (inventorySignerAddress) {
|
|
306
|
+
txSenders.push(this.toBytea(inventorySignerAddress));
|
|
307
|
+
}
|
|
308
|
+
|
|
293
309
|
const variables = {
|
|
294
310
|
senders: bridges.map((a) => this.toBytea(a)),
|
|
295
311
|
recipients: bridges.map((a) => this.toBytea(a)),
|
|
296
312
|
originTxRecipients: routers.map((a) => this.toBytea(a)),
|
|
297
313
|
originDomains: domains,
|
|
298
314
|
destDomains: domains,
|
|
299
|
-
|
|
315
|
+
txSenders,
|
|
300
316
|
limit,
|
|
301
317
|
};
|
|
302
318
|
|
|
@@ -309,7 +325,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
309
325
|
$originTxRecipients: [bytea!],
|
|
310
326
|
$originDomains: [Int!],
|
|
311
327
|
$destDomains: [Int!],
|
|
312
|
-
$
|
|
328
|
+
$txSenders: [bytea!],
|
|
313
329
|
$limit: Int = 100
|
|
314
330
|
) {
|
|
315
331
|
message_view(
|
|
@@ -321,7 +337,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
321
337
|
{ origin_tx_recipient: { _in: $originTxRecipients } },
|
|
322
338
|
{ origin_domain_id: { _in: $originDomains } },
|
|
323
339
|
{ destination_domain_id: { _in: $destDomains } },
|
|
324
|
-
{ origin_tx_sender: {
|
|
340
|
+
{ origin_tx_sender: { _in: $txSenders } }
|
|
325
341
|
]
|
|
326
342
|
}
|
|
327
343
|
order_by: { origin_tx_id: desc }
|
|
@@ -337,6 +353,7 @@ export class ExplorerClient implements IExplorerClient {
|
|
|
337
353
|
origin_tx_recipient
|
|
338
354
|
is_delivered
|
|
339
355
|
message_body
|
|
356
|
+
send_occurred_at
|
|
340
357
|
}
|
|
341
358
|
}`;
|
|
342
359
|
|
|
@@ -11,10 +11,12 @@ describe('bridgeConfig', () => {
|
|
|
11
11
|
it('should return the base bridge config when no overrides exist', () => {
|
|
12
12
|
const bridges: ChainMap<BridgeConfigWithOverride> = {
|
|
13
13
|
chain1: {
|
|
14
|
+
executionType: 'movableCollateral',
|
|
14
15
|
bridge: '0x1234567890123456789012345678901234567890',
|
|
15
16
|
bridgeMinAcceptedAmount: 1000,
|
|
16
17
|
},
|
|
17
18
|
chain2: {
|
|
19
|
+
executionType: 'movableCollateral',
|
|
18
20
|
bridge: '0x0987654321098765432109876543210987654321',
|
|
19
21
|
bridgeMinAcceptedAmount: 2000,
|
|
20
22
|
},
|
|
@@ -23,6 +25,7 @@ describe('bridgeConfig', () => {
|
|
|
23
25
|
const result = getBridgeConfig(bridges, 'chain1', 'chain2');
|
|
24
26
|
|
|
25
27
|
expect(result).to.deep.equal({
|
|
28
|
+
executionType: 'movableCollateral',
|
|
26
29
|
bridge: '0x1234567890123456789012345678901234567890',
|
|
27
30
|
bridgeMinAcceptedAmount: 1000,
|
|
28
31
|
});
|
|
@@ -31,6 +34,7 @@ describe('bridgeConfig', () => {
|
|
|
31
34
|
it('should merge base config with overrides when they exist', () => {
|
|
32
35
|
const bridges: ChainMap<BridgeConfigWithOverride> = {
|
|
33
36
|
chain1: {
|
|
37
|
+
executionType: 'movableCollateral',
|
|
34
38
|
bridge: '0x1234567890123456789012345678901234567890',
|
|
35
39
|
bridgeMinAcceptedAmount: 1000,
|
|
36
40
|
override: {
|
|
@@ -40,6 +44,7 @@ describe('bridgeConfig', () => {
|
|
|
40
44
|
},
|
|
41
45
|
},
|
|
42
46
|
chain2: {
|
|
47
|
+
executionType: 'movableCollateral',
|
|
43
48
|
bridge: '0x0987654321098765432109876543210987654321',
|
|
44
49
|
bridgeMinAcceptedAmount: 2000,
|
|
45
50
|
},
|
|
@@ -48,6 +53,7 @@ describe('bridgeConfig', () => {
|
|
|
48
53
|
const result = getBridgeConfig(bridges, 'chain1', 'chain2');
|
|
49
54
|
|
|
50
55
|
expect(result).to.deep.equal({
|
|
56
|
+
executionType: 'movableCollateral',
|
|
51
57
|
bridge: '0x1234567890123456789012345678901234567890',
|
|
52
58
|
bridgeMinAcceptedAmount: 5000,
|
|
53
59
|
});
|
|
@@ -56,6 +62,7 @@ describe('bridgeConfig', () => {
|
|
|
56
62
|
it('should handle overrides that change the bridge address', () => {
|
|
57
63
|
const bridges: ChainMap<BridgeConfigWithOverride> = {
|
|
58
64
|
chain1: {
|
|
65
|
+
executionType: 'movableCollateral',
|
|
59
66
|
bridge: '0x1234567890123456789012345678901234567890',
|
|
60
67
|
bridgeMinAcceptedAmount: 1000,
|
|
61
68
|
override: {
|
|
@@ -65,6 +72,7 @@ describe('bridgeConfig', () => {
|
|
|
65
72
|
},
|
|
66
73
|
},
|
|
67
74
|
chain2: {
|
|
75
|
+
executionType: 'movableCollateral',
|
|
68
76
|
bridge: '0x0987654321098765432109876543210987654321',
|
|
69
77
|
bridgeMinAcceptedAmount: 2000,
|
|
70
78
|
},
|
|
@@ -73,6 +81,7 @@ describe('bridgeConfig', () => {
|
|
|
73
81
|
const result = getBridgeConfig(bridges, 'chain1', 'chain2');
|
|
74
82
|
|
|
75
83
|
expect(result).to.deep.equal({
|
|
84
|
+
executionType: 'movableCollateral',
|
|
76
85
|
bridge: '0xABCDEF0123456789ABCDEF0123456789ABCDEF01',
|
|
77
86
|
bridgeMinAcceptedAmount: 1000,
|
|
78
87
|
});
|
package/src/utils/bridgeUtils.ts
CHANGED
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
import type { ChainMap, ChainName } from '@hyperlane-xyz/sdk';
|
|
2
|
+
import type { Address } from '@hyperlane-xyz/utils';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import type { ExternalBridgeType } from '../config/types.js';
|
|
5
|
+
import type { StrategyRoute } from '../interfaces/IStrategy.js';
|
|
6
|
+
|
|
7
|
+
type BaseBridgeConfig = {
|
|
8
|
+
bridgeMinAcceptedAmount?: string | number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type MovableCollateralBridgeConfig = BaseBridgeConfig & {
|
|
12
|
+
executionType: 'movableCollateral';
|
|
13
|
+
bridge: Address;
|
|
5
14
|
};
|
|
6
15
|
|
|
7
|
-
export type
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
export type InventoryBridgeConfig = BaseBridgeConfig & {
|
|
17
|
+
executionType: 'inventory';
|
|
18
|
+
externalBridge: ExternalBridgeType;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type BridgeConfig =
|
|
22
|
+
| MovableCollateralBridgeConfig
|
|
23
|
+
| InventoryBridgeConfig;
|
|
24
|
+
|
|
25
|
+
export function isMovableCollateralConfig(
|
|
26
|
+
config: BridgeConfig,
|
|
27
|
+
): config is MovableCollateralBridgeConfig {
|
|
28
|
+
return config.executionType === 'movableCollateral';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isInventoryConfig(
|
|
32
|
+
config: BridgeConfig,
|
|
33
|
+
): config is InventoryBridgeConfig {
|
|
34
|
+
return config.executionType === 'inventory';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type BridgeConfigWithOverride = BridgeConfig & {
|
|
38
|
+
override?: ChainMap<Partial<BridgeConfig>>;
|
|
10
39
|
};
|
|
11
40
|
|
|
12
41
|
/**
|
|
@@ -28,5 +57,45 @@ export function getBridgeConfig(
|
|
|
28
57
|
const { override: _, ...baseConfig } = fromConfig;
|
|
29
58
|
|
|
30
59
|
// Return a new object with the base config and any overrides
|
|
31
|
-
return { ...baseConfig, ...routeSpecificOverrides };
|
|
60
|
+
return { ...baseConfig, ...routeSpecificOverrides } as BridgeConfig;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a StrategyRoute from a BridgeConfig with exhaustive type checking
|
|
65
|
+
* @param bridgeConfig The bridge configuration
|
|
66
|
+
* @param origin The origin chain
|
|
67
|
+
* @param destination The destination chain
|
|
68
|
+
* @param amount The amount to transfer
|
|
69
|
+
* @returns A StrategyRoute with the appropriate execution type
|
|
70
|
+
*/
|
|
71
|
+
export function createStrategyRoute(
|
|
72
|
+
bridgeConfig: BridgeConfig,
|
|
73
|
+
origin: ChainName,
|
|
74
|
+
destination: ChainName,
|
|
75
|
+
amount: bigint,
|
|
76
|
+
): StrategyRoute {
|
|
77
|
+
switch (bridgeConfig.executionType) {
|
|
78
|
+
case 'inventory':
|
|
79
|
+
return {
|
|
80
|
+
origin,
|
|
81
|
+
destination,
|
|
82
|
+
amount,
|
|
83
|
+
executionType: 'inventory',
|
|
84
|
+
externalBridge: bridgeConfig.externalBridge,
|
|
85
|
+
};
|
|
86
|
+
case 'movableCollateral':
|
|
87
|
+
return {
|
|
88
|
+
origin,
|
|
89
|
+
destination,
|
|
90
|
+
amount,
|
|
91
|
+
executionType: 'movableCollateral',
|
|
92
|
+
bridge: bridgeConfig.bridge,
|
|
93
|
+
};
|
|
94
|
+
default: {
|
|
95
|
+
const _exhaustive: never = bridgeConfig;
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Unknown execution type: ${(_exhaustive as BridgeConfig).executionType}`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
32
101
|
}
|