@humanode-hyperlane/rebalancer 27.2.2-humanode.1 → 1029.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 +3 -3
- package/dist/bridges/LiFiBridge.d.ts.map +1 -1
- package/dist/bridges/LiFiBridge.js +66 -55
- package/dist/bridges/LiFiBridge.js.map +1 -1
- package/dist/bridges/LiFiBridge.test.js +213 -0
- package/dist/bridges/LiFiBridge.test.js.map +1 -1
- package/dist/config/RebalancerConfig.d.ts +4 -3
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +7 -5
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +278 -2
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +707 -2664
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +62 -7
- package/dist/config/types.js.map +1 -1
- package/dist/core/InventoryRebalancer.d.ts +13 -19
- package/dist/core/InventoryRebalancer.d.ts.map +1 -1
- package/dist/core/InventoryRebalancer.js +404 -276
- package/dist/core/InventoryRebalancer.js.map +1 -1
- package/dist/core/InventoryRebalancer.test.js +814 -25
- package/dist/core/InventoryRebalancer.test.js.map +1 -1
- package/dist/core/Rebalancer.d.ts.map +1 -1
- package/dist/core/Rebalancer.js +12 -6
- package/dist/core/Rebalancer.js.map +1 -1
- package/dist/core/Rebalancer.test.js +51 -0
- package/dist/core/Rebalancer.test.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.d.ts.map +1 -1
- package/dist/core/RebalancerOrchestrator.test.js +0 -1
- package/dist/core/RebalancerOrchestrator.test.js.map +1 -1
- package/dist/core/RebalancerService.d.ts.map +1 -1
- package/dist/core/RebalancerService.js +3 -2
- package/dist/core/RebalancerService.js.map +1 -1
- package/dist/core/RebalancerService.test.js +24 -0
- package/dist/core/RebalancerService.test.js.map +1 -1
- package/dist/e2e/fixtures/routes.d.ts +3 -3
- package/dist/e2e/fixtures/routes.d.ts.map +1 -1
- package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/BaseLocalDeploymentManager.js +3 -2
- package/dist/e2e/harness/BaseLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/ForkIndexer.d.ts.map +1 -1
- package/dist/e2e/harness/ForkIndexer.js.map +1 -1
- package/dist/e2e/harness/LocalProvider.d.ts +3 -0
- package/dist/e2e/harness/LocalProvider.d.ts.map +1 -0
- package/dist/e2e/harness/LocalProvider.js +9 -0
- package/dist/e2e/harness/LocalProvider.js.map +1 -0
- package/dist/e2e/harness/LocalProvider.test.d.ts +2 -0
- package/dist/e2e/harness/LocalProvider.test.d.ts.map +1 -0
- package/dist/e2e/harness/LocalProvider.test.js +14 -0
- package/dist/e2e/harness/LocalProvider.test.js.map +1 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/MixedLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/MockExplorerClient.d.ts.map +1 -1
- package/dist/e2e/harness/MockExplorerClient.js.map +1 -1
- package/dist/e2e/harness/MockExternalBridge.d.ts.map +1 -1
- package/dist/e2e/harness/MockExternalBridge.js.map +1 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.js +2 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/SnapshotHelper.d.ts.map +1 -1
- package/dist/e2e/harness/SnapshotHelper.js +3 -5
- package/dist/e2e/harness/SnapshotHelper.js.map +1 -1
- package/dist/e2e/harness/TestHelpers.js +1 -2
- package/dist/e2e/harness/TestHelpers.js.map +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts +5 -1
- package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -1
- package/dist/e2e/harness/TestRebalancer.js +14 -4
- package/dist/e2e/harness/TestRebalancer.js.map +1 -1
- package/dist/e2e/relayer-denylist.e2e-test.d.ts +2 -0
- package/dist/e2e/relayer-denylist.e2e-test.d.ts.map +1 -0
- package/dist/e2e/relayer-denylist.e2e-test.js +388 -0
- package/dist/e2e/relayer-denylist.e2e-test.js.map +1 -0
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
- package/dist/factories/RebalancerContextFactory.js +61 -31
- package/dist/factories/RebalancerContextFactory.js.map +1 -1
- package/dist/factories/RebalancerContextFactory.test.js +336 -5
- package/dist/factories/RebalancerContextFactory.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IRebalancer.d.ts +4 -2
- package/dist/interfaces/IRebalancer.d.ts.map +1 -1
- package/dist/metrics/Metrics.d.ts.map +1 -1
- package/dist/metrics/Metrics.js +1 -1
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/metrics/PriceGetter.d.ts +1 -0
- package/dist/metrics/PriceGetter.d.ts.map +1 -1
- package/dist/metrics/PriceGetter.js +14 -4
- package/dist/metrics/PriceGetter.js.map +1 -1
- package/dist/metrics/PriceGetter.test.d.ts +2 -0
- package/dist/metrics/PriceGetter.test.d.ts.map +1 -0
- package/dist/metrics/PriceGetter.test.js +84 -0
- package/dist/metrics/PriceGetter.test.js.map +1 -0
- package/dist/metrics/scripts/metrics.d.ts +4 -4
- package/dist/monitor/Monitor.d.ts +1 -0
- package/dist/monitor/Monitor.d.ts.map +1 -1
- package/dist/monitor/Monitor.js +55 -46
- package/dist/monitor/Monitor.js.map +1 -1
- package/dist/monitor/Monitor.test.d.ts +2 -0
- package/dist/monitor/Monitor.test.d.ts.map +1 -0
- package/dist/monitor/Monitor.test.js +346 -0
- package/dist/monitor/Monitor.test.js.map +1 -0
- package/dist/service.d.ts +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +9 -5
- package/dist/service.js.map +1 -1
- package/dist/strategy/BaseStrategy.d.ts.map +1 -1
- package/dist/strategy/BaseStrategy.js +13 -11
- package/dist/strategy/BaseStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.js +2 -2
- package/dist/strategy/CollateralDeficitStrategy.js.map +1 -1
- package/dist/strategy/CompositeStrategy.d.ts.map +1 -1
- package/dist/strategy/CompositeStrategy.js.map +1 -1
- package/dist/strategy/CompositeStrategy.test.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.d.ts +1 -0
- package/dist/strategy/MinAmountStrategy.d.ts.map +1 -1
- package/dist/strategy/MinAmountStrategy.js +12 -8
- package/dist/strategy/MinAmountStrategy.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.test.js +189 -2
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
- package/dist/strategy/StrategyFactory.d.ts.map +1 -1
- package/dist/strategy/StrategyFactory.js.map +1 -1
- package/dist/strategy/WeightedStrategy.d.ts.map +1 -1
- package/dist/test/helpers.d.ts +11 -3
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +9 -11
- package/dist/test/helpers.js.map +1 -1
- package/dist/test/lifiMocks.d.ts +6 -6
- package/dist/test/lifiMocks.d.ts.map +1 -1
- package/dist/test/lifiMocks.js +5 -2
- package/dist/test/lifiMocks.js.map +1 -1
- package/dist/test/pendingTransferMiddlewareMocks.d.ts +17 -0
- package/dist/test/pendingTransferMiddlewareMocks.d.ts.map +1 -0
- package/dist/test/pendingTransferMiddlewareMocks.js +43 -0
- package/dist/test/pendingTransferMiddlewareMocks.js.map +1 -0
- package/dist/tracking/ActionTracker.d.ts +4 -0
- package/dist/tracking/ActionTracker.d.ts.map +1 -1
- package/dist/tracking/ActionTracker.js +76 -9
- package/dist/tracking/ActionTracker.js.map +1 -1
- package/dist/tracking/ActionTracker.test.js +418 -1
- package/dist/tracking/ActionTracker.test.js.map +1 -1
- package/dist/tracking/IActionTracker.d.ts +4 -2
- package/dist/tracking/IActionTracker.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.js.map +1 -1
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts +64 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js +474 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js +1168 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts +61 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js +160 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js +369 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts +60 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js +288 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js +606 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts +25 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js +41 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js +141 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts +12 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.js +29 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts +59 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js +661 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js +1093 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/types.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/types.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/types.js +4 -0
- package/dist/tracking/pendingTransferMiddlewares/types.js.map +1 -0
- package/dist/tracking/store/InMemoryStore.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.d.ts +1 -0
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +8 -3
- package/dist/utils/ExplorerClient.js.map +1 -1
- package/dist/utils/ExplorerClient.test.js +25 -0
- package/dist/utils/ExplorerClient.test.js.map +1 -1
- package/dist/utils/balanceUtils.d.ts +7 -1
- package/dist/utils/balanceUtils.d.ts.map +1 -1
- package/dist/utils/balanceUtils.js +39 -1
- package/dist/utils/balanceUtils.js.map +1 -1
- package/dist/utils/balanceUtils.test.js +55 -1
- package/dist/utils/balanceUtils.test.js.map +1 -1
- package/dist/utils/blockTag.d.ts +5 -4
- package/dist/utils/blockTag.d.ts.map +1 -1
- package/dist/utils/blockTag.js +26 -10
- package/dist/utils/blockTag.js.map +1 -1
- package/dist/utils/blockTag.test.d.ts +2 -0
- package/dist/utils/blockTag.test.d.ts.map +1 -0
- package/dist/utils/blockTag.test.js +132 -0
- package/dist/utils/blockTag.test.js.map +1 -0
- package/dist/utils/bridgeUtils.js.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/gasEstimation.d.ts +2 -1
- package/dist/utils/gasEstimation.d.ts.map +1 -1
- package/dist/utils/gasEstimation.js +16 -13
- package/dist/utils/gasEstimation.js.map +1 -1
- package/dist/utils/gasEstimation.test.d.ts +2 -0
- package/dist/utils/gasEstimation.test.d.ts.map +1 -0
- package/dist/utils/gasEstimation.test.js +104 -0
- package/dist/utils/gasEstimation.test.js.map +1 -0
- package/dist/utils/tokenUtils.d.ts.map +1 -1
- package/dist/utils/tokenUtils.js +5 -2
- package/dist/utils/tokenUtils.js.map +1 -1
- package/package.json +23 -22
- package/src/bridges/LiFiBridge.test.ts +270 -0
- package/src/bridges/LiFiBridge.ts +90 -71
- package/src/config/RebalancerConfig.test.ts +315 -1
- package/src/config/RebalancerConfig.ts +6 -3
- package/src/config/types.ts +98 -8
- package/src/core/InventoryRebalancer.test.ts +1092 -38
- package/src/core/InventoryRebalancer.ts +584 -351
- package/src/core/Rebalancer.test.ts +84 -0
- package/src/core/Rebalancer.ts +22 -6
- package/src/core/RebalancerOrchestrator.test.ts +0 -1
- package/src/core/RebalancerService.test.ts +35 -0
- package/src/core/RebalancerService.ts +3 -2
- package/src/e2e/harness/BaseLocalDeploymentManager.ts +3 -1
- package/src/e2e/harness/LocalProvider.test.ts +16 -0
- package/src/e2e/harness/LocalProvider.ts +10 -0
- package/src/e2e/harness/NativeLocalDeploymentManager.ts +2 -1
- package/src/e2e/harness/SnapshotHelper.ts +2 -5
- package/src/e2e/harness/TestHelpers.ts +3 -3
- package/src/e2e/harness/TestRebalancer.ts +21 -1
- package/src/e2e/relayer-denylist.e2e-test.ts +558 -0
- package/src/factories/RebalancerContextFactory.test.ts +489 -8
- package/src/factories/RebalancerContextFactory.ts +86 -36
- package/src/index.ts +2 -0
- package/src/interfaces/IRebalancer.ts +4 -1
- package/src/metrics/Metrics.ts +1 -0
- package/src/metrics/PriceGetter.test.ts +113 -0
- package/src/metrics/PriceGetter.ts +18 -3
- package/src/monitor/Monitor.test.ts +408 -0
- package/src/monitor/Monitor.ts +123 -97
- package/src/service.ts +14 -8
- package/src/strategy/BaseStrategy.ts +18 -15
- package/src/strategy/CollateralDeficitStrategy.ts +4 -3
- package/src/strategy/MinAmountStrategy.test.ts +238 -2
- package/src/strategy/MinAmountStrategy.ts +29 -17
- package/src/test/helpers.ts +13 -12
- package/src/test/lifiMocks.ts +5 -2
- package/src/test/pendingTransferMiddlewareMocks.ts +65 -0
- package/src/tracking/ActionTracker.test.ts +635 -3
- package/src/tracking/ActionTracker.ts +92 -12
- package/src/tracking/IActionTracker.ts +4 -2
- package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.ts +1693 -0
- package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.ts +784 -0
- package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.ts +554 -0
- package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.ts +233 -0
- package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.ts +894 -0
- package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.ts +404 -0
- package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.ts +205 -0
- package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.ts +89 -0
- package/src/tracking/pendingTransferMiddlewares/fixtures/mainnet-denylist.json +3556 -0
- package/src/tracking/pendingTransferMiddlewares/matchBody.ts +43 -0
- package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.ts +1220 -0
- package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.ts +934 -0
- package/src/tracking/pendingTransferMiddlewares/types.ts +3 -0
- package/src/utils/ExplorerClient.test.ts +42 -0
- package/src/utils/ExplorerClient.ts +14 -3
- package/src/utils/balanceUtils.test.ts +87 -1
- package/src/utils/balanceUtils.ts +73 -2
- package/src/utils/blockTag.test.ts +173 -0
- package/src/utils/blockTag.ts +35 -15
- package/src/utils/gasEstimation.test.ts +192 -0
- package/src/utils/gasEstimation.ts +17 -11
- package/src/utils/tokenUtils.ts +5 -2
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
import chai, { expect } from 'chai';
|
|
2
2
|
import chaiAsPromised from 'chai-as-promised';
|
|
3
|
-
import {
|
|
3
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { type Logger, pino } from 'pino';
|
|
4
8
|
import Sinon from 'sinon';
|
|
5
9
|
|
|
6
10
|
import { EthJsonRpcBlockParameterTag } from '@humanode-hyperlane/sdk';
|
|
11
|
+
import { ProtocolType, assert } from '@humanode-hyperlane/utils';
|
|
7
12
|
|
|
8
13
|
import {
|
|
9
14
|
DEFAULT_INTENT_TTL_MS,
|
|
10
15
|
DEFAULT_MOVEMENT_STALENESS_MS,
|
|
11
16
|
ExternalBridgeType,
|
|
12
17
|
} from '../config/types.js';
|
|
13
|
-
import
|
|
18
|
+
import {
|
|
19
|
+
ID_A,
|
|
20
|
+
ID_B,
|
|
21
|
+
ID_C,
|
|
22
|
+
buildMessage,
|
|
23
|
+
} from '../test/pendingTransferMiddlewareMocks.js';
|
|
24
|
+
import {
|
|
25
|
+
ExplorerClient,
|
|
26
|
+
type ExplorerMessage,
|
|
27
|
+
} from '../utils/ExplorerClient.js';
|
|
14
28
|
|
|
15
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
ActionTracker,
|
|
31
|
+
type ActionTrackerConfig,
|
|
32
|
+
TRANSFER_SYNC_ROW_LIMIT_MESSAGE,
|
|
33
|
+
} from './ActionTracker.js';
|
|
34
|
+
import { ExplorerRowLimitError } from './pendingTransferMiddlewares/PendingTransferMiddleware.js';
|
|
35
|
+
import { RelayerDenylistMiddleware } from './pendingTransferMiddlewares/RelayerDenylistMiddleware.js';
|
|
16
36
|
import { InMemoryStore } from './store/InMemoryStore.js';
|
|
17
37
|
import type { RebalanceAction, RebalanceIntent, Transfer } from './types.js';
|
|
18
38
|
|
|
@@ -349,6 +369,50 @@ describe('ActionTracker', () => {
|
|
|
349
369
|
expect(transfers).to.have.lengthOf(1);
|
|
350
370
|
});
|
|
351
371
|
|
|
372
|
+
interface SyncFailureCase {
|
|
373
|
+
name: string;
|
|
374
|
+
error: Error;
|
|
375
|
+
loggedAsError: boolean;
|
|
376
|
+
}
|
|
377
|
+
const syncFailures: SyncFailureCase[] = [
|
|
378
|
+
{
|
|
379
|
+
name: 'logs an Explorer row limit failure as an error and rethrows it',
|
|
380
|
+
error: new ExplorerRowLimitError('row limit', []),
|
|
381
|
+
loggedAsError: true,
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'rethrows other Explorer failures without an error log',
|
|
385
|
+
error: new Error('explorer down'),
|
|
386
|
+
loggedAsError: false,
|
|
387
|
+
},
|
|
388
|
+
];
|
|
389
|
+
for (const c of syncFailures) {
|
|
390
|
+
it(c.name, async () => {
|
|
391
|
+
const logger: Logger = pino({ level: 'silent' });
|
|
392
|
+
const error = Sinon.spy(logger, 'error');
|
|
393
|
+
explorerClient.getInflightUserTransfers.rejects(c.error);
|
|
394
|
+
const tracker = new ActionTracker(
|
|
395
|
+
transferStore,
|
|
396
|
+
rebalanceIntentStore,
|
|
397
|
+
rebalanceActionStore,
|
|
398
|
+
explorerClient,
|
|
399
|
+
core,
|
|
400
|
+
config,
|
|
401
|
+
logger,
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
await expect(tracker.syncTransfers()).to.be.rejectedWith(c.error);
|
|
405
|
+
|
|
406
|
+
expect(
|
|
407
|
+
error.calledWith(
|
|
408
|
+
Sinon.match({ error: c.error.message }),
|
|
409
|
+
TRANSFER_SYNC_ROW_LIMIT_MESSAGE,
|
|
410
|
+
),
|
|
411
|
+
).to.equal(c.loggedAsError);
|
|
412
|
+
expect(error.callCount).to.equal(c.loggedAsError ? 1 : 0);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
352
416
|
it('should mark transfers as complete when delivered', async () => {
|
|
353
417
|
// Pre-create transfer
|
|
354
418
|
await transferStore.save({
|
|
@@ -372,6 +436,123 @@ describe('ActionTracker', () => {
|
|
|
372
436
|
const transfer = await transferStore.get('0xmsg1');
|
|
373
437
|
expect(transfer?.status).to.equal('complete');
|
|
374
438
|
});
|
|
439
|
+
|
|
440
|
+
describe('with an ignored-transfer predicate', () => {
|
|
441
|
+
const trackedTransfer: Transfer = {
|
|
442
|
+
id: '0xmsg1',
|
|
443
|
+
status: 'in_progress',
|
|
444
|
+
messageId: '0xmsg1',
|
|
445
|
+
origin: 1,
|
|
446
|
+
destination: 2,
|
|
447
|
+
amount: 100n,
|
|
448
|
+
sender: '0xuser1',
|
|
449
|
+
recipient: '0xuser2',
|
|
450
|
+
createdAt: 1_000,
|
|
451
|
+
updatedAt: 1_000,
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
function createTracker(
|
|
455
|
+
isIgnoredTransfer: (messageId: string) => boolean,
|
|
456
|
+
logger: Logger = testLogger,
|
|
457
|
+
): ActionTracker {
|
|
458
|
+
return new ActionTracker(
|
|
459
|
+
transferStore,
|
|
460
|
+
rebalanceIntentStore,
|
|
461
|
+
rebalanceActionStore,
|
|
462
|
+
explorerClient,
|
|
463
|
+
core,
|
|
464
|
+
{
|
|
465
|
+
routersByDomain: config.routersByDomain,
|
|
466
|
+
isIgnoredTransfer,
|
|
467
|
+
bridges: config.bridges,
|
|
468
|
+
rebalancerAddress: config.rebalancerAddress,
|
|
469
|
+
intentTTL: config.intentTTL,
|
|
470
|
+
},
|
|
471
|
+
logger,
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
it('keeps an ignored tracked transfer stored but excludes it from in-progress transfers without checking delivery', async () => {
|
|
476
|
+
await transferStore.save(trackedTransfer);
|
|
477
|
+
const tracker = createTracker((id) => id === '0xmsg1');
|
|
478
|
+
|
|
479
|
+
await tracker.syncTransfers();
|
|
480
|
+
|
|
481
|
+
const transfer = await tracker.getTransfer('0xmsg1');
|
|
482
|
+
expect(transfer?.status).to.equal('in_progress');
|
|
483
|
+
expect(await tracker.getInProgressTransfers()).to.deep.equal([]);
|
|
484
|
+
expect(mailboxStub.isDelivered.called).to.be.false;
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('reserves an ignored transfer again once it is no longer ignored, even when absent from the Explorer result', async () => {
|
|
488
|
+
await transferStore.save(trackedTransfer);
|
|
489
|
+
let ignored = true;
|
|
490
|
+
const tracker = createTracker((id) => ignored && id === '0xmsg1');
|
|
491
|
+
explorerClient.getInflightUserTransfers.resolves([]);
|
|
492
|
+
|
|
493
|
+
await tracker.syncTransfers();
|
|
494
|
+
expect(await tracker.getInProgressTransfers()).to.deep.equal([]);
|
|
495
|
+
|
|
496
|
+
ignored = false;
|
|
497
|
+
await tracker.syncTransfers();
|
|
498
|
+
|
|
499
|
+
const inProgress = await tracker.getInProgressTransfers();
|
|
500
|
+
expect(inProgress.map((t) => [t.id, t.amount])).to.deep.equal([
|
|
501
|
+
['0xmsg1', 100n],
|
|
502
|
+
]);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('completes an ignored transfer on the first sync after it is no longer ignored once delivered', async () => {
|
|
506
|
+
await transferStore.save(trackedTransfer);
|
|
507
|
+
let ignored = true;
|
|
508
|
+
const tracker = createTracker((id) => ignored && id === '0xmsg1');
|
|
509
|
+
mailboxStub.isDelivered.resolves(true);
|
|
510
|
+
|
|
511
|
+
await tracker.syncTransfers();
|
|
512
|
+
expect(mailboxStub.isDelivered.called).to.be.false;
|
|
513
|
+
expect((await tracker.getTransfer('0xmsg1'))?.status).to.equal(
|
|
514
|
+
'in_progress',
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
ignored = false;
|
|
518
|
+
await tracker.syncTransfers();
|
|
519
|
+
|
|
520
|
+
expect(mailboxStub.isDelivered.calledOnce).to.be.true;
|
|
521
|
+
expect((await tracker.getTransfer('0xmsg1'))?.status).to.equal(
|
|
522
|
+
'complete',
|
|
523
|
+
);
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('keeps a tracked transfer the predicate does not ignore', async () => {
|
|
527
|
+
await transferStore.save(trackedTransfer);
|
|
528
|
+
|
|
529
|
+
await createTracker((id) => id === '0xother').syncTransfers();
|
|
530
|
+
|
|
531
|
+
const transfer = await transferStore.get('0xmsg1');
|
|
532
|
+
|
|
533
|
+
expect(transfer?.status).to.equal('in_progress');
|
|
534
|
+
expect(mailboxStub.isDelivered.calledOnce).to.be.true;
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('counts an ignored transfer on every sync while it stays ignored', async () => {
|
|
538
|
+
await transferStore.save(trackedTransfer);
|
|
539
|
+
const logger: Logger = pino({ level: 'silent' });
|
|
540
|
+
const info = Sinon.spy(logger, 'info');
|
|
541
|
+
const tracker = createTracker((id) => id === '0xmsg1', logger);
|
|
542
|
+
|
|
543
|
+
await tracker.syncTransfers();
|
|
544
|
+
await tracker.syncTransfers();
|
|
545
|
+
|
|
546
|
+
const syncedCounts = info
|
|
547
|
+
.getCalls()
|
|
548
|
+
.filter((call) => call.args.includes('Transfers synced'))
|
|
549
|
+
.map((call) => call.args[0]);
|
|
550
|
+
expect(syncedCounts).to.deep.equal([
|
|
551
|
+
{ newTransfers: 0, completed: 0, ignored: 1, inProgress: 0 },
|
|
552
|
+
{ newTransfers: 0, completed: 0, ignored: 1, inProgress: 0 },
|
|
553
|
+
]);
|
|
554
|
+
});
|
|
555
|
+
});
|
|
375
556
|
});
|
|
376
557
|
|
|
377
558
|
describe('syncRebalanceIntents', () => {
|
|
@@ -565,6 +746,231 @@ describe('ActionTracker', () => {
|
|
|
565
746
|
});
|
|
566
747
|
});
|
|
567
748
|
|
|
749
|
+
describe('with a relayer denylist middleware', () => {
|
|
750
|
+
let dir: string;
|
|
751
|
+
let denylistPath: string;
|
|
752
|
+
|
|
753
|
+
beforeEach(() => {
|
|
754
|
+
dir = mkdtempSync(join(tmpdir(), 'action-tracker-denylist-'));
|
|
755
|
+
denylistPath = join(dir, 'denylist.json');
|
|
756
|
+
writeDenylist([]);
|
|
757
|
+
explorerClient.getInflightRebalanceActions.resolves([
|
|
758
|
+
buildMessage(ID_A),
|
|
759
|
+
buildMessage(ID_B),
|
|
760
|
+
buildMessage(ID_C),
|
|
761
|
+
]);
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
afterEach(() => {
|
|
765
|
+
rmSync(dir, { recursive: true, force: true });
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
function writeDenylist(
|
|
769
|
+
messageIds: string[],
|
|
770
|
+
matches: Record<string, unknown>[] = [],
|
|
771
|
+
): void {
|
|
772
|
+
writeFileSync(
|
|
773
|
+
denylistPath,
|
|
774
|
+
JSON.stringify({
|
|
775
|
+
rules: [
|
|
776
|
+
...messageIds.map((messageId) => ({ messageId })),
|
|
777
|
+
...matches,
|
|
778
|
+
].map((match) => ({ reason: 'settled', addedBy: 'tester', match })),
|
|
779
|
+
}),
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
async function createDenylistTracker(): Promise<ActionTracker> {
|
|
784
|
+
const middleware = await RelayerDenylistMiddleware.create(
|
|
785
|
+
explorerClient,
|
|
786
|
+
{ url: pathToFileURL(denylistPath).href, refreshIntervalMs: 0 },
|
|
787
|
+
testLogger,
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
return new ActionTracker(
|
|
791
|
+
transferStore,
|
|
792
|
+
rebalanceIntentStore,
|
|
793
|
+
rebalanceActionStore,
|
|
794
|
+
middleware,
|
|
795
|
+
core,
|
|
796
|
+
{
|
|
797
|
+
routersByDomain: config.routersByDomain,
|
|
798
|
+
isIgnoredTransfer: (id) => middleware.isIgnored(id),
|
|
799
|
+
isIgnoredRebalanceAction: (id) =>
|
|
800
|
+
middleware.isIgnoredRebalanceAction(id),
|
|
801
|
+
bridges: config.bridges,
|
|
802
|
+
rebalancerAddress: config.rebalancerAddress,
|
|
803
|
+
intentTTL: config.intentTTL,
|
|
804
|
+
},
|
|
805
|
+
testLogger,
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
async function activeIntentMessageIds(
|
|
810
|
+
tracker: ActionTracker,
|
|
811
|
+
): Promise<string[]> {
|
|
812
|
+
const actions = await rebalanceActionStore.getAll();
|
|
813
|
+
const intents = await tracker.getActiveRebalanceIntents();
|
|
814
|
+
|
|
815
|
+
return intents.map((intent) => {
|
|
816
|
+
const action = actions.find((a) => a.intentId === intent.id);
|
|
817
|
+
assert(action?.messageId, `Missing action for intent ${intent.id}`);
|
|
818
|
+
return action.messageId;
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
it('does not recover denylisted rebalance messages at startup', async () => {
|
|
823
|
+
writeDenylist([ID_A, ID_B]);
|
|
824
|
+
const tracker = await createDenylistTracker();
|
|
825
|
+
|
|
826
|
+
await tracker.initialize();
|
|
827
|
+
|
|
828
|
+
const actions = await rebalanceActionStore.getAll();
|
|
829
|
+
expect(actions.map((a) => a.id)).to.deep.equal([ID_C]);
|
|
830
|
+
const intents = await rebalanceIntentStore.getAll();
|
|
831
|
+
expect(intents.map((i) => [i.status, i.amount])).to.deep.equal([
|
|
832
|
+
['in_progress', 100n],
|
|
833
|
+
]);
|
|
834
|
+
expect(await activeIntentMessageIds(tracker)).to.deep.equal([ID_C]);
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('stops counting a tracked rebalance message once it is denylisted without changing its status', async () => {
|
|
838
|
+
const tracker = await createDenylistTracker();
|
|
839
|
+
await tracker.initialize();
|
|
840
|
+
expect(await activeIntentMessageIds(tracker)).to.have.members([
|
|
841
|
+
ID_A,
|
|
842
|
+
ID_B,
|
|
843
|
+
ID_C,
|
|
844
|
+
]);
|
|
845
|
+
|
|
846
|
+
writeDenylist([ID_A]);
|
|
847
|
+
mailboxStub.isDelivered.resetHistory();
|
|
848
|
+
await tracker.syncRebalanceActions();
|
|
849
|
+
|
|
850
|
+
expect(await activeIntentMessageIds(tracker)).to.have.members([
|
|
851
|
+
ID_B,
|
|
852
|
+
ID_C,
|
|
853
|
+
]);
|
|
854
|
+
const ignoredAction = await rebalanceActionStore.get(ID_A);
|
|
855
|
+
assert(ignoredAction, 'Expected the ignored action to stay stored');
|
|
856
|
+
expect(ignoredAction.status).to.equal('in_progress');
|
|
857
|
+
expect(
|
|
858
|
+
(await rebalanceIntentStore.get(ignoredAction.intentId))?.status,
|
|
859
|
+
).to.equal('in_progress');
|
|
860
|
+
expect(mailboxStub.isDelivered.calledWith(ID_A)).to.be.true;
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
it('completes a denylisted rebalance message the relayer still delivers', async () => {
|
|
864
|
+
const tracker = await createDenylistTracker();
|
|
865
|
+
await tracker.initialize();
|
|
866
|
+
writeDenylist([ID_A]);
|
|
867
|
+
mailboxStub.isDelivered.callsFake(async (id: string) => id === ID_A);
|
|
868
|
+
|
|
869
|
+
await tracker.syncRebalanceActions();
|
|
870
|
+
|
|
871
|
+
const action = await rebalanceActionStore.get(ID_A);
|
|
872
|
+
assert(action, 'Expected the delivered action to stay stored');
|
|
873
|
+
expect(action.status).to.equal('complete');
|
|
874
|
+
expect(
|
|
875
|
+
(await rebalanceIntentStore.get(action.intentId))?.status,
|
|
876
|
+
).to.equal('complete');
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
it('still fails a denylisted rebalance message past the intent TTL', async () => {
|
|
880
|
+
await rebalanceIntentStore.save({
|
|
881
|
+
id: 'expired-intent',
|
|
882
|
+
status: 'in_progress',
|
|
883
|
+
origin: 42161,
|
|
884
|
+
destination: 1,
|
|
885
|
+
amount: 100n,
|
|
886
|
+
createdAt: 0,
|
|
887
|
+
updatedAt: 0,
|
|
888
|
+
});
|
|
889
|
+
await rebalanceActionStore.save({
|
|
890
|
+
id: ID_A,
|
|
891
|
+
type: 'rebalance_message',
|
|
892
|
+
status: 'in_progress',
|
|
893
|
+
intentId: 'expired-intent',
|
|
894
|
+
messageId: ID_A,
|
|
895
|
+
origin: 42161,
|
|
896
|
+
destination: 1,
|
|
897
|
+
amount: 100n,
|
|
898
|
+
createdAt: 0,
|
|
899
|
+
updatedAt: 0,
|
|
900
|
+
});
|
|
901
|
+
writeDenylist([ID_A]);
|
|
902
|
+
const tracker = await createDenylistTracker();
|
|
903
|
+
await tracker.syncRebalanceActions();
|
|
904
|
+
expect(await activeIntentMessageIds(tracker)).to.have.members([
|
|
905
|
+
ID_B,
|
|
906
|
+
ID_C,
|
|
907
|
+
]);
|
|
908
|
+
|
|
909
|
+
await tracker.syncRebalanceIntents();
|
|
910
|
+
|
|
911
|
+
expect((await rebalanceActionStore.get(ID_A))?.status).to.equal('failed');
|
|
912
|
+
expect(
|
|
913
|
+
(await rebalanceIntentStore.get('expired-intent'))?.status,
|
|
914
|
+
).to.equal('failed');
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
it('keeps ignoring a denylisted rebalance message pushed off the Explorer page', async () => {
|
|
918
|
+
const tracker = await createDenylistTracker();
|
|
919
|
+
await tracker.initialize();
|
|
920
|
+
writeDenylist([ID_A]);
|
|
921
|
+
await tracker.syncRebalanceActions();
|
|
922
|
+
expect(await activeIntentMessageIds(tracker)).to.not.include(ID_A);
|
|
923
|
+
|
|
924
|
+
const newerIds = Array.from(
|
|
925
|
+
{ length: 100 },
|
|
926
|
+
(_, i) => `0x${(i + 1).toString(16).padStart(64, '0')}`,
|
|
927
|
+
);
|
|
928
|
+
explorerClient.getInflightRebalanceActions.resolves(
|
|
929
|
+
newerIds.map((id) => buildMessage(id)),
|
|
930
|
+
);
|
|
931
|
+
await tracker.syncRebalanceActions();
|
|
932
|
+
|
|
933
|
+
const countedIds = await activeIntentMessageIds(tracker);
|
|
934
|
+
expect(countedIds).to.not.include(ID_A);
|
|
935
|
+
expect(countedIds).to.include.members([ID_B, ID_C, ...newerIds]);
|
|
936
|
+
|
|
937
|
+
writeDenylist([]);
|
|
938
|
+
await tracker.syncRebalanceActions();
|
|
939
|
+
|
|
940
|
+
expect(await activeIntentMessageIds(tracker)).to.include(ID_A);
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
it('keeps recovering and counting rebalance messages a broad rule denies', async () => {
|
|
944
|
+
writeDenylist([], [{ destinationDomain: 1 }, { originDomain: 42161 }]);
|
|
945
|
+
const tracker = await createDenylistTracker();
|
|
946
|
+
|
|
947
|
+
await tracker.initialize();
|
|
948
|
+
await tracker.syncRebalanceActions();
|
|
949
|
+
|
|
950
|
+
expect(await activeIntentMessageIds(tracker)).to.have.members([
|
|
951
|
+
ID_A,
|
|
952
|
+
ID_B,
|
|
953
|
+
ID_C,
|
|
954
|
+
]);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
it('counts a rebalance message again once its rule is removed', async () => {
|
|
958
|
+
writeDenylist([ID_A, ID_B]);
|
|
959
|
+
const tracker = await createDenylistTracker();
|
|
960
|
+
await tracker.initialize();
|
|
961
|
+
expect(await activeIntentMessageIds(tracker)).to.deep.equal([ID_C]);
|
|
962
|
+
|
|
963
|
+
writeDenylist([]);
|
|
964
|
+
await tracker.syncRebalanceActions();
|
|
965
|
+
|
|
966
|
+
expect(await activeIntentMessageIds(tracker)).to.have.members([
|
|
967
|
+
ID_A,
|
|
968
|
+
ID_B,
|
|
969
|
+
ID_C,
|
|
970
|
+
]);
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
|
|
568
974
|
describe('syncInventoryMovementActions', () => {
|
|
569
975
|
it('stores pending status on in-progress movement', async () => {
|
|
570
976
|
await rebalanceActionStore.save({
|
|
@@ -746,6 +1152,125 @@ describe('ActionTracker', () => {
|
|
|
746
1152
|
expect(result).to.have.lengthOf(1);
|
|
747
1153
|
expect(result[0].id).to.equal('intent-2');
|
|
748
1154
|
});
|
|
1155
|
+
|
|
1156
|
+
describe('with an ignored-rebalance-action predicate', () => {
|
|
1157
|
+
const ignoredIds = new Set(['0xignored1', '0xignored2']);
|
|
1158
|
+
|
|
1159
|
+
function createTracker(
|
|
1160
|
+
isIgnoredRebalanceAction?: (messageId: string) => boolean,
|
|
1161
|
+
): ActionTracker {
|
|
1162
|
+
return new ActionTracker(
|
|
1163
|
+
transferStore,
|
|
1164
|
+
rebalanceIntentStore,
|
|
1165
|
+
rebalanceActionStore,
|
|
1166
|
+
explorerClient,
|
|
1167
|
+
core,
|
|
1168
|
+
{
|
|
1169
|
+
routersByDomain: config.routersByDomain,
|
|
1170
|
+
isIgnoredRebalanceAction,
|
|
1171
|
+
bridges: config.bridges,
|
|
1172
|
+
rebalancerAddress: config.rebalancerAddress,
|
|
1173
|
+
intentTTL: config.intentTTL,
|
|
1174
|
+
},
|
|
1175
|
+
testLogger,
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
async function saveIntent(
|
|
1180
|
+
id: string,
|
|
1181
|
+
executionMethod?: 'movable_collateral' | 'inventory',
|
|
1182
|
+
): Promise<void> {
|
|
1183
|
+
await rebalanceIntentStore.save({
|
|
1184
|
+
id,
|
|
1185
|
+
status: 'in_progress',
|
|
1186
|
+
origin: 1,
|
|
1187
|
+
destination: 2,
|
|
1188
|
+
amount: 300n,
|
|
1189
|
+
executionMethod,
|
|
1190
|
+
createdAt: Date.now(),
|
|
1191
|
+
updatedAt: Date.now(),
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
async function saveAction(
|
|
1196
|
+
id: string,
|
|
1197
|
+
intentId: string,
|
|
1198
|
+
type: 'rebalance_message' | 'inventory_deposit',
|
|
1199
|
+
status: 'in_progress' | 'complete',
|
|
1200
|
+
): Promise<void> {
|
|
1201
|
+
await rebalanceActionStore.save({
|
|
1202
|
+
id,
|
|
1203
|
+
type,
|
|
1204
|
+
status,
|
|
1205
|
+
intentId,
|
|
1206
|
+
messageId: id,
|
|
1207
|
+
origin: 1,
|
|
1208
|
+
destination: 2,
|
|
1209
|
+
amount: 100n,
|
|
1210
|
+
createdAt: Date.now(),
|
|
1211
|
+
updatedAt: Date.now(),
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
it('drops only intents whose in-progress messages are all ignored', async () => {
|
|
1216
|
+
await saveIntent('all-ignored', 'movable_collateral');
|
|
1217
|
+
await saveAction(
|
|
1218
|
+
'0xignored1',
|
|
1219
|
+
'all-ignored',
|
|
1220
|
+
'rebalance_message',
|
|
1221
|
+
'in_progress',
|
|
1222
|
+
);
|
|
1223
|
+
await saveAction(
|
|
1224
|
+
'0xdone',
|
|
1225
|
+
'all-ignored',
|
|
1226
|
+
'rebalance_message',
|
|
1227
|
+
'complete',
|
|
1228
|
+
);
|
|
1229
|
+
await saveIntent('mixed');
|
|
1230
|
+
await saveAction(
|
|
1231
|
+
'0xignored2',
|
|
1232
|
+
'mixed',
|
|
1233
|
+
'rebalance_message',
|
|
1234
|
+
'in_progress',
|
|
1235
|
+
);
|
|
1236
|
+
await saveAction('0xkept', 'mixed', 'rebalance_message', 'in_progress');
|
|
1237
|
+
await saveIntent('no-actions', 'movable_collateral');
|
|
1238
|
+
|
|
1239
|
+
const result = await createTracker((id) =>
|
|
1240
|
+
ignoredIds.has(id),
|
|
1241
|
+
).getActiveRebalanceIntents();
|
|
1242
|
+
|
|
1243
|
+
expect(result.map((i) => [i.id, i.amount])).to.have.deep.members([
|
|
1244
|
+
['mixed', 300n],
|
|
1245
|
+
['no-actions', 300n],
|
|
1246
|
+
]);
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
it('leaves inventory intents and their retry state untouched', async () => {
|
|
1250
|
+
await saveIntent('inventory', 'inventory');
|
|
1251
|
+
await saveAction(
|
|
1252
|
+
'0xignored1',
|
|
1253
|
+
'inventory',
|
|
1254
|
+
'inventory_deposit',
|
|
1255
|
+
'in_progress',
|
|
1256
|
+
);
|
|
1257
|
+
|
|
1258
|
+
const withoutPredicate = createTracker();
|
|
1259
|
+
const withPredicate = createTracker((id) => ignoredIds.has(id));
|
|
1260
|
+
|
|
1261
|
+
expect(
|
|
1262
|
+
(await withPredicate.getActiveRebalanceIntents()).map((i) => i.id),
|
|
1263
|
+
).to.deep.equal(['inventory']);
|
|
1264
|
+
expect(
|
|
1265
|
+
await withPredicate.getPartiallyFulfilledInventoryIntents(),
|
|
1266
|
+
).to.deep.equal(
|
|
1267
|
+
await withoutPredicate.getPartiallyFulfilledInventoryIntents(),
|
|
1268
|
+
);
|
|
1269
|
+
expect(
|
|
1270
|
+
await withPredicate.getPartiallyFulfilledInventoryIntents(),
|
|
1271
|
+
).to.have.lengthOf(1);
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
749
1274
|
});
|
|
750
1275
|
|
|
751
1276
|
describe('getPartiallyFulfilledInventoryIntents', () => {
|
|
@@ -807,6 +1332,53 @@ describe('ActionTracker', () => {
|
|
|
807
1332
|
expect(partialIntents[0].remaining).to.equal(600000000000000000n); // 0.6 ETH remaining
|
|
808
1333
|
});
|
|
809
1334
|
|
|
1335
|
+
it('ignores inventory_movement amounts when computing remaining', async () => {
|
|
1336
|
+
await rebalanceIntentStore.save({
|
|
1337
|
+
id: 'partial-intent-with-movement',
|
|
1338
|
+
status: 'in_progress',
|
|
1339
|
+
origin: 1,
|
|
1340
|
+
destination: 2,
|
|
1341
|
+
amount: 1000000000000000000n,
|
|
1342
|
+
executionMethod: 'inventory',
|
|
1343
|
+
createdAt: Date.now(),
|
|
1344
|
+
updatedAt: Date.now(),
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
await rebalanceActionStore.save({
|
|
1348
|
+
id: 'action-deposit',
|
|
1349
|
+
type: 'inventory_deposit',
|
|
1350
|
+
status: 'complete',
|
|
1351
|
+
intentId: 'partial-intent-with-movement',
|
|
1352
|
+
origin: 1,
|
|
1353
|
+
destination: 2,
|
|
1354
|
+
amount: 400000000000000000n,
|
|
1355
|
+
createdAt: Date.now(),
|
|
1356
|
+
updatedAt: Date.now(),
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
await rebalanceActionStore.save({
|
|
1360
|
+
id: 'action-movement',
|
|
1361
|
+
type: 'inventory_movement',
|
|
1362
|
+
status: 'complete',
|
|
1363
|
+
intentId: 'partial-intent-with-movement',
|
|
1364
|
+
origin: 3,
|
|
1365
|
+
destination: 2,
|
|
1366
|
+
amount: 9000000000000000000n,
|
|
1367
|
+
createdAt: Date.now(),
|
|
1368
|
+
updatedAt: Date.now(),
|
|
1369
|
+
});
|
|
1370
|
+
|
|
1371
|
+
const partialIntents =
|
|
1372
|
+
await tracker.getPartiallyFulfilledInventoryIntents();
|
|
1373
|
+
|
|
1374
|
+
expect(partialIntents).to.have.lengthOf(1);
|
|
1375
|
+
expect(partialIntents[0].intent.id).to.equal(
|
|
1376
|
+
'partial-intent-with-movement',
|
|
1377
|
+
);
|
|
1378
|
+
expect(partialIntents[0].completedAmount).to.equal(400000000000000000n);
|
|
1379
|
+
expect(partialIntents[0].remaining).to.equal(600000000000000000n);
|
|
1380
|
+
});
|
|
1381
|
+
|
|
810
1382
|
it('does not return non-inventory intents', async () => {
|
|
811
1383
|
// Create a not_started intent without executionMethod: 'inventory'
|
|
812
1384
|
await rebalanceIntentStore.save({
|
|
@@ -1484,6 +2056,66 @@ describe('ActionTracker', () => {
|
|
|
1484
2056
|
expect(updatedAction?.status).to.equal('complete');
|
|
1485
2057
|
});
|
|
1486
2058
|
|
|
2059
|
+
it('checks tracked delivery with the real Explorer client and no bridges', async () => {
|
|
2060
|
+
const intent: RebalanceIntent = {
|
|
2061
|
+
id: 'intent-1',
|
|
2062
|
+
status: 'in_progress',
|
|
2063
|
+
origin: 1,
|
|
2064
|
+
destination: 2,
|
|
2065
|
+
amount: 100n,
|
|
2066
|
+
createdAt: Date.now(),
|
|
2067
|
+
updatedAt: Date.now(),
|
|
2068
|
+
};
|
|
2069
|
+
|
|
2070
|
+
const action: RebalanceAction = {
|
|
2071
|
+
id: 'action-1',
|
|
2072
|
+
type: 'inventory_deposit',
|
|
2073
|
+
status: 'in_progress',
|
|
2074
|
+
intentId: 'intent-1',
|
|
2075
|
+
messageId: '0xmsg1',
|
|
2076
|
+
origin: 1,
|
|
2077
|
+
destination: 2,
|
|
2078
|
+
amount: 100n,
|
|
2079
|
+
createdAt: Date.now(),
|
|
2080
|
+
updatedAt: Date.now(),
|
|
2081
|
+
};
|
|
2082
|
+
|
|
2083
|
+
await rebalanceIntentStore.save(intent);
|
|
2084
|
+
await rebalanceActionStore.save(action);
|
|
2085
|
+
|
|
2086
|
+
config.bridges = [];
|
|
2087
|
+
const fetchStub = Sinon.stub(globalThis, 'fetch').rejects(
|
|
2088
|
+
new Error('unexpected HTTP'),
|
|
2089
|
+
);
|
|
2090
|
+
tracker = new ActionTracker(
|
|
2091
|
+
transferStore,
|
|
2092
|
+
rebalanceIntentStore,
|
|
2093
|
+
rebalanceActionStore,
|
|
2094
|
+
new ExplorerClient(
|
|
2095
|
+
'https://explorer.test',
|
|
2096
|
+
() => ProtocolType.Ethereum,
|
|
2097
|
+
),
|
|
2098
|
+
core,
|
|
2099
|
+
config,
|
|
2100
|
+
testLogger,
|
|
2101
|
+
);
|
|
2102
|
+
mailboxStub.isDelivered.resolves(true);
|
|
2103
|
+
|
|
2104
|
+
try {
|
|
2105
|
+
await tracker.syncRebalanceActions();
|
|
2106
|
+
expect(fetchStub.called).to.be.false;
|
|
2107
|
+
} finally {
|
|
2108
|
+
fetchStub.restore();
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
expect(mailboxStub.isDelivered.calledOnce).to.be.true;
|
|
2112
|
+
const call = mailboxStub.isDelivered.firstCall;
|
|
2113
|
+
expect(call.args[0]).to.equal('0xmsg1');
|
|
2114
|
+
|
|
2115
|
+
const updatedAction = await rebalanceActionStore.get('action-1');
|
|
2116
|
+
expect(updatedAction?.status).to.equal('complete');
|
|
2117
|
+
});
|
|
2118
|
+
|
|
1487
2119
|
it('should keep transfer in_progress when not delivered', async () => {
|
|
1488
2120
|
await transferStore.save({
|
|
1489
2121
|
id: '0xmsg1',
|