@humanode-hyperlane/rebalancer 0.0.0-stage → 27.2.2-humanode.1
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/LICENSE.md +193 -0
- package/README.md +297 -2
- package/dist/bridges/LiFiBridge.d.ts +93 -0
- package/dist/bridges/LiFiBridge.d.ts.map +1 -0
- package/dist/bridges/LiFiBridge.js +527 -0
- package/dist/bridges/LiFiBridge.js.map +1 -0
- package/dist/bridges/LiFiBridge.test.d.ts +2 -0
- package/dist/bridges/LiFiBridge.test.d.ts.map +1 -0
- package/dist/bridges/LiFiBridge.test.js +504 -0
- package/dist/bridges/LiFiBridge.test.js.map +1 -0
- package/dist/config/RebalancerConfig.d.ts +20 -0
- package/dist/config/RebalancerConfig.d.ts.map +1 -0
- package/dist/config/RebalancerConfig.js +35 -0
- package/dist/config/RebalancerConfig.js.map +1 -0
- package/dist/config/RebalancerConfig.test.d.ts +2 -0
- package/dist/config/RebalancerConfig.test.d.ts.map +1 -0
- package/dist/config/RebalancerConfig.test.js +798 -0
- package/dist/config/RebalancerConfig.test.js.map +1 -0
- package/dist/config/types.d.ts +3008 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +451 -0
- package/dist/config/types.js.map +1 -0
- package/dist/core/InventoryRebalancer.d.ts +201 -0
- package/dist/core/InventoryRebalancer.d.ts.map +1 -0
- package/dist/core/InventoryRebalancer.js +994 -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 +1511 -0
- package/dist/core/InventoryRebalancer.test.js.map +1 -0
- package/dist/core/Rebalancer.d.ts +37 -0
- package/dist/core/Rebalancer.d.ts.map +1 -0
- package/dist/core/Rebalancer.js +433 -0
- package/dist/core/Rebalancer.js.map +1 -0
- 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 +424 -0
- package/dist/core/Rebalancer.test.js.map +1 -0
- package/dist/core/RebalancerOrchestrator.d.ts +56 -0
- package/dist/core/RebalancerOrchestrator.d.ts.map +1 -0
- package/dist/core/RebalancerOrchestrator.js +154 -0
- package/dist/core/RebalancerOrchestrator.js.map +1 -0
- 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 +721 -0
- package/dist/core/RebalancerOrchestrator.test.js.map +1 -0
- package/dist/core/RebalancerService.d.ts +127 -0
- package/dist/core/RebalancerService.d.ts.map +1 -0
- package/dist/core/RebalancerService.js +270 -0
- package/dist/core/RebalancerService.js.map +1 -0
- 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 +777 -0
- package/dist/core/RebalancerService.test.js.map +1 -0
- package/dist/e2e/collateral-deficit.e2e-test.d.ts +2 -0
- package/dist/e2e/collateral-deficit.e2e-test.d.ts.map +1 -0
- package/dist/e2e/collateral-deficit.e2e-test.js +227 -0
- package/dist/e2e/collateral-deficit.e2e-test.js.map +1 -0
- package/dist/e2e/composite.e2e-test.d.ts +2 -0
- package/dist/e2e/composite.e2e-test.d.ts.map +1 -0
- package/dist/e2e/composite.e2e-test.js +666 -0
- package/dist/e2e/composite.e2e-test.js.map +1 -0
- package/dist/e2e/fixtures/routes.d.ts +89 -0
- package/dist/e2e/fixtures/routes.d.ts.map +1 -0
- package/dist/e2e/fixtures/routes.js +420 -0
- package/dist/e2e/fixtures/routes.js.map +1 -0
- package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts +38 -0
- package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts.map +1 -0
- package/dist/e2e/harness/BaseLocalDeploymentManager.js +144 -0
- package/dist/e2e/harness/BaseLocalDeploymentManager.js.map +1 -0
- package/dist/e2e/harness/BridgeSetup.d.ts +11 -0
- package/dist/e2e/harness/BridgeSetup.d.ts.map +1 -0
- package/dist/e2e/harness/BridgeSetup.js +50 -0
- package/dist/e2e/harness/BridgeSetup.js.map +1 -0
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts +13 -0
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts.map +1 -0
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js +105 -0
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js.map +1 -0
- package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts +11 -0
- package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts.map +1 -0
- package/dist/e2e/harness/Erc20LocalDeploymentManager.js +105 -0
- package/dist/e2e/harness/Erc20LocalDeploymentManager.js.map +1 -0
- package/dist/e2e/harness/ForkIndexer.d.ts +23 -0
- package/dist/e2e/harness/ForkIndexer.d.ts.map +1 -0
- package/dist/e2e/harness/ForkIndexer.js +127 -0
- package/dist/e2e/harness/ForkIndexer.js.map +1 -0
- package/dist/e2e/harness/ForkIndexer.test.d.ts +2 -0
- package/dist/e2e/harness/ForkIndexer.test.d.ts.map +1 -0
- package/dist/e2e/harness/ForkIndexer.test.js +257 -0
- package/dist/e2e/harness/ForkIndexer.test.js.map +1 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts +21 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts.map +1 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.js +115 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.js.map +1 -0
- package/dist/e2e/harness/MockExplorerClient.d.ts +23 -0
- package/dist/e2e/harness/MockExplorerClient.d.ts.map +1 -0
- package/dist/e2e/harness/MockExplorerClient.js +57 -0
- package/dist/e2e/harness/MockExplorerClient.js.map +1 -0
- package/dist/e2e/harness/MockExternalBridge.d.ts +32 -0
- package/dist/e2e/harness/MockExternalBridge.d.ts.map +1 -0
- package/dist/e2e/harness/MockExternalBridge.js +247 -0
- package/dist/e2e/harness/MockExternalBridge.js.map +1 -0
- package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts +13 -0
- package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts.map +1 -0
- package/dist/e2e/harness/NativeLocalDeploymentManager.js +91 -0
- package/dist/e2e/harness/NativeLocalDeploymentManager.js.map +1 -0
- package/dist/e2e/harness/SnapshotHelper.d.ts +13 -0
- package/dist/e2e/harness/SnapshotHelper.d.ts.map +1 -0
- package/dist/e2e/harness/SnapshotHelper.js +36 -0
- package/dist/e2e/harness/SnapshotHelper.js.map +1 -0
- package/dist/e2e/harness/TestHelpers.d.ts +25 -0
- package/dist/e2e/harness/TestHelpers.d.ts.map +1 -0
- package/dist/e2e/harness/TestHelpers.js +103 -0
- package/dist/e2e/harness/TestHelpers.js.map +1 -0
- package/dist/e2e/harness/TestRebalancer.d.ts +85 -0
- package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -0
- package/dist/e2e/harness/TestRebalancer.js +427 -0
- package/dist/e2e/harness/TestRebalancer.js.map +1 -0
- package/dist/e2e/harness/TransferHelper.d.ts +34 -0
- package/dist/e2e/harness/TransferHelper.d.ts.map +1 -0
- package/dist/e2e/harness/TransferHelper.js +93 -0
- package/dist/e2e/harness/TransferHelper.js.map +1 -0
- package/dist/e2e/inventory-erc20-minAmount.e2e-test.d.ts +2 -0
- package/dist/e2e/inventory-erc20-minAmount.e2e-test.d.ts.map +1 -0
- package/dist/e2e/inventory-erc20-minAmount.e2e-test.js +411 -0
- package/dist/e2e/inventory-erc20-minAmount.e2e-test.js.map +1 -0
- package/dist/e2e/inventory-erc20-weighted.e2e-test.d.ts +2 -0
- package/dist/e2e/inventory-erc20-weighted.e2e-test.d.ts.map +1 -0
- package/dist/e2e/inventory-erc20-weighted.e2e-test.js +408 -0
- package/dist/e2e/inventory-erc20-weighted.e2e-test.js.map +1 -0
- package/dist/e2e/inventory-minAmount.e2e-test.d.ts +2 -0
- package/dist/e2e/inventory-minAmount.e2e-test.d.ts.map +1 -0
- package/dist/e2e/inventory-minAmount.e2e-test.js +411 -0
- package/dist/e2e/inventory-minAmount.e2e-test.js.map +1 -0
- package/dist/e2e/inventory-weighted.e2e-test.d.ts +2 -0
- package/dist/e2e/inventory-weighted.e2e-test.d.ts.map +1 -0
- package/dist/e2e/inventory-weighted.e2e-test.js +409 -0
- package/dist/e2e/inventory-weighted.e2e-test.js.map +1 -0
- package/dist/e2e/minAmount.e2e-test.d.ts +2 -0
- package/dist/e2e/minAmount.e2e-test.d.ts.map +1 -0
- package/dist/e2e/minAmount.e2e-test.js +203 -0
- package/dist/e2e/minAmount.e2e-test.js.map +1 -0
- package/dist/e2e/mixed-weighted.e2e-test.d.ts +2 -0
- package/dist/e2e/mixed-weighted.e2e-test.d.ts.map +1 -0
- package/dist/e2e/mixed-weighted.e2e-test.js +189 -0
- package/dist/e2e/mixed-weighted.e2e-test.js.map +1 -0
- package/dist/e2e/weighted.e2e-test.d.ts +2 -0
- package/dist/e2e/weighted.e2e-test.d.ts.map +1 -0
- package/dist/e2e/weighted.e2e-test.js +198 -0
- package/dist/e2e/weighted.e2e-test.js.map +1 -0
- package/dist/factories/RebalancerContextFactory.d.ts +89 -0
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -0
- package/dist/factories/RebalancerContextFactory.js +420 -0
- package/dist/factories/RebalancerContextFactory.js.map +1 -0
- package/dist/factories/RebalancerContextFactory.test.d.ts +2 -0
- package/dist/factories/RebalancerContextFactory.test.d.ts.map +1 -0
- package/dist/factories/RebalancerContextFactory.test.js +270 -0
- package/dist/factories/RebalancerContextFactory.test.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/IExternalBridge.d.ts +103 -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/IMetrics.d.ts +5 -0
- package/dist/interfaces/IMetrics.d.ts.map +1 -0
- package/dist/interfaces/IMetrics.js +2 -0
- package/dist/interfaces/IMetrics.js.map +1 -0
- package/dist/interfaces/IMonitor.d.ts +50 -0
- package/dist/interfaces/IMonitor.d.ts.map +1 -0
- package/dist/interfaces/IMonitor.js +14 -0
- package/dist/interfaces/IMonitor.js.map +1 -0
- package/dist/interfaces/IRebalancer.d.ts +31 -0
- package/dist/interfaces/IRebalancer.d.ts.map +1 -0
- package/dist/interfaces/IRebalancer.js +2 -0
- package/dist/interfaces/IRebalancer.js.map +1 -0
- package/dist/interfaces/IStrategy.d.ts +60 -0
- package/dist/interfaces/IStrategy.d.ts.map +1 -0
- package/dist/interfaces/IStrategy.js +13 -0
- package/dist/interfaces/IStrategy.js.map +1 -0
- package/dist/metrics/Metrics.d.ts +25 -0
- package/dist/metrics/Metrics.d.ts.map +1 -0
- package/dist/metrics/Metrics.js +164 -0
- package/dist/metrics/Metrics.js.map +1 -0
- package/dist/metrics/PriceGetter.d.ts +10 -0
- package/dist/metrics/PriceGetter.d.ts.map +1 -0
- package/dist/metrics/PriceGetter.js +41 -0
- package/dist/metrics/PriceGetter.js.map +1 -0
- package/dist/metrics/scripts/metrics.d.ts +28 -0
- package/dist/metrics/scripts/metrics.d.ts.map +1 -0
- package/dist/metrics/scripts/metrics.js +61 -0
- package/dist/metrics/scripts/metrics.js.map +1 -0
- package/dist/monitor/Monitor.d.ts +40 -0
- package/dist/monitor/Monitor.d.ts.map +1 -0
- package/dist/monitor/Monitor.js +211 -0
- package/dist/monitor/Monitor.js.map +1 -0
- package/dist/service.d.ts +3 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +205 -0
- package/dist/service.js.map +1 -0
- package/dist/strategy/BaseStrategy.d.ts +86 -0
- package/dist/strategy/BaseStrategy.d.ts.map +1 -0
- package/dist/strategy/BaseStrategy.js +342 -0
- package/dist/strategy/BaseStrategy.js.map +1 -0
- package/dist/strategy/CollateralDeficitStrategy.d.ts +65 -0
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -0
- package/dist/strategy/CollateralDeficitStrategy.js +253 -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 +497 -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 +278 -0
- package/dist/strategy/CompositeStrategy.test.js.map +1 -0
- package/dist/strategy/MinAmountStrategy.d.ts +35 -0
- package/dist/strategy/MinAmountStrategy.d.ts.map +1 -0
- package/dist/strategy/MinAmountStrategy.js +112 -0
- package/dist/strategy/MinAmountStrategy.js.map +1 -0
- package/dist/strategy/MinAmountStrategy.test.d.ts +2 -0
- package/dist/strategy/MinAmountStrategy.test.d.ts.map +1 -0
- package/dist/strategy/MinAmountStrategy.test.js +547 -0
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -0
- package/dist/strategy/StrategyFactory.d.ts +27 -0
- package/dist/strategy/StrategyFactory.d.ts.map +1 -0
- package/dist/strategy/StrategyFactory.js +79 -0
- package/dist/strategy/StrategyFactory.js.map +1 -0
- package/dist/strategy/StrategyFactory.test.d.ts +2 -0
- package/dist/strategy/StrategyFactory.test.d.ts.map +1 -0
- package/dist/strategy/StrategyFactory.test.js +81 -0
- package/dist/strategy/StrategyFactory.test.js.map +1 -0
- package/dist/strategy/WeightedStrategy.d.ts +32 -0
- package/dist/strategy/WeightedStrategy.d.ts.map +1 -0
- package/dist/strategy/WeightedStrategy.js +73 -0
- package/dist/strategy/WeightedStrategy.js.map +1 -0
- package/dist/strategy/WeightedStrategy.test.d.ts +2 -0
- package/dist/strategy/WeightedStrategy.test.d.ts.map +1 -0
- package/dist/strategy/WeightedStrategy.test.js +403 -0
- package/dist/strategy/WeightedStrategy.test.js.map +1 -0
- package/dist/strategy/index.d.ts +7 -0
- package/dist/strategy/index.d.ts.map +1 -0
- package/dist/strategy/index.js +7 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/test/helpers.d.ts +99 -0
- package/dist/test/helpers.d.ts.map +1 -0
- package/dist/test/helpers.js +311 -0
- package/dist/test/helpers.js.map +1 -0
- package/dist/test/lifiMocks.d.ts +52 -0
- package/dist/test/lifiMocks.d.ts.map +1 -0
- package/dist/test/lifiMocks.js +160 -0
- package/dist/test/lifiMocks.js.map +1 -0
- package/dist/tracking/ActionTracker.d.ts +90 -0
- package/dist/tracking/ActionTracker.d.ts.map +1 -0
- package/dist/tracking/ActionTracker.js +678 -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 +1351 -0
- package/dist/tracking/ActionTracker.test.js.map +1 -0
- package/dist/tracking/IActionTracker.d.ts +157 -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 +52 -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 +175 -0
- package/dist/tracking/InflightContextAdapter.test.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 +77 -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 +68 -0
- package/dist/utils/ExplorerClient.d.ts.map +1 -0
- package/dist/utils/ExplorerClient.js +324 -0
- package/dist/utils/ExplorerClient.js.map +1 -0
- package/dist/utils/ExplorerClient.test.d.ts +2 -0
- package/dist/utils/ExplorerClient.test.d.ts.map +1 -0
- package/dist/utils/ExplorerClient.test.js +261 -0
- package/dist/utils/ExplorerClient.test.js.map +1 -0
- package/dist/utils/balanceUtils.d.ts +12 -0
- package/dist/utils/balanceUtils.d.ts.map +1 -0
- package/dist/utils/balanceUtils.js +40 -0
- package/dist/utils/balanceUtils.js.map +1 -0
- package/dist/utils/balanceUtils.test.d.ts +2 -0
- package/dist/utils/balanceUtils.test.d.ts.map +1 -0
- package/dist/utils/balanceUtils.test.js +55 -0
- package/dist/utils/balanceUtils.test.js.map +1 -0
- package/dist/utils/blockTag.d.ts +14 -0
- package/dist/utils/blockTag.d.ts.map +1 -0
- package/dist/utils/blockTag.js +46 -0
- package/dist/utils/blockTag.js.map +1 -0
- package/dist/utils/bridgeUtils.d.ts +40 -0
- package/dist/utils/bridgeUtils.d.ts.map +1 -0
- package/dist/utils/bridgeUtils.js +54 -0
- package/dist/utils/bridgeUtils.js.map +1 -0
- package/dist/utils/bridgeUtils.test.d.ts +2 -0
- package/dist/utils/bridgeUtils.test.d.ts.map +1 -0
- package/dist/utils/bridgeUtils.test.js +163 -0
- package/dist/utils/bridgeUtils.test.js.map +1 -0
- package/dist/utils/errors.d.ts +4 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +6 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/gasEstimation.d.ts +65 -0
- package/dist/utils/gasEstimation.d.ts.map +1 -0
- package/dist/utils/gasEstimation.js +206 -0
- package/dist/utils/gasEstimation.js.map +1 -0
- package/dist/utils/solanaKeyParser.d.ts +10 -0
- package/dist/utils/solanaKeyParser.d.ts.map +1 -0
- package/dist/utils/solanaKeyParser.js +87 -0
- package/dist/utils/solanaKeyParser.js.map +1 -0
- package/dist/utils/solanaKeyParser.test.d.ts +2 -0
- package/dist/utils/solanaKeyParser.test.d.ts.map +1 -0
- package/dist/utils/solanaKeyParser.test.js +71 -0
- package/dist/utils/solanaKeyParser.test.js.map +1 -0
- package/dist/utils/tokenUtils.d.ts +38 -0
- package/dist/utils/tokenUtils.d.ts.map +1 -0
- package/dist/utils/tokenUtils.js +65 -0
- package/dist/utils/tokenUtils.js.map +1 -0
- package/dist/utils/transactionUtils.d.ts +22 -0
- package/dist/utils/transactionUtils.d.ts.map +1 -0
- package/dist/utils/transactionUtils.js +26 -0
- package/dist/utils/transactionUtils.js.map +1 -0
- package/package.json +87 -3
- package/src/bridges/LiFiBridge.test.ts +615 -0
- package/src/bridges/LiFiBridge.ts +731 -0
- package/src/config/RebalancerConfig.test.ts +921 -0
- package/src/config/RebalancerConfig.ts +63 -0
- package/src/config/types.ts +613 -0
- package/src/core/InventoryRebalancer.test.ts +1858 -0
- package/src/core/InventoryRebalancer.ts +1455 -0
- package/src/core/Rebalancer.test.ts +686 -0
- package/src/core/Rebalancer.ts +686 -0
- package/src/core/RebalancerOrchestrator.test.ts +871 -0
- package/src/core/RebalancerOrchestrator.ts +273 -0
- package/src/core/RebalancerService.test.ts +1094 -0
- package/src/core/RebalancerService.ts +412 -0
- package/src/e2e/E2E_TEST_CONVENTIONS.md +222 -0
- package/src/e2e/collateral-deficit.e2e-test.ts +403 -0
- package/src/e2e/composite.e2e-test.ts +1008 -0
- package/src/e2e/fixtures/routes.ts +532 -0
- package/src/e2e/harness/BaseLocalDeploymentManager.ts +246 -0
- package/src/e2e/harness/BridgeSetup.ts +95 -0
- package/src/e2e/harness/Erc20InventoryLocalDeploymentManager.ts +183 -0
- package/src/e2e/harness/Erc20LocalDeploymentManager.ts +190 -0
- package/src/e2e/harness/ForkIndexer.test.ts +448 -0
- package/src/e2e/harness/ForkIndexer.ts +183 -0
- package/src/e2e/harness/MixedLocalDeploymentManager.ts +196 -0
- package/src/e2e/harness/MockExplorerClient.ts +94 -0
- package/src/e2e/harness/MockExternalBridge.ts +411 -0
- package/src/e2e/harness/NativeLocalDeploymentManager.ts +138 -0
- package/src/e2e/harness/SnapshotHelper.ts +56 -0
- package/src/e2e/harness/TestHelpers.ts +169 -0
- package/src/e2e/harness/TestRebalancer.ts +758 -0
- package/src/e2e/harness/TransferHelper.ts +188 -0
- package/src/e2e/inventory-erc20-minAmount.e2e-test.ts +735 -0
- package/src/e2e/inventory-erc20-weighted.e2e-test.ts +733 -0
- package/src/e2e/inventory-minAmount.e2e-test.ts +734 -0
- package/src/e2e/inventory-weighted.e2e-test.ts +734 -0
- package/src/e2e/minAmount.e2e-test.ts +313 -0
- package/src/e2e/mixed-weighted.e2e-test.ts +267 -0
- package/src/e2e/weighted.e2e-test.ts +304 -0
- package/src/factories/RebalancerContextFactory.test.ts +394 -0
- package/src/factories/RebalancerContextFactory.ts +771 -0
- package/src/index.ts +125 -0
- package/src/interfaces/IExternalBridge.ts +117 -0
- package/src/interfaces/IMetrics.ts +5 -0
- package/src/interfaces/IMonitor.ts +71 -0
- package/src/interfaces/IRebalancer.ts +57 -0
- package/src/interfaces/IStrategy.ts +81 -0
- package/src/metrics/Metrics.ts +335 -0
- package/src/metrics/PriceGetter.ts +74 -0
- package/src/metrics/scripts/metrics.ts +139 -0
- package/src/monitor/Monitor.ts +324 -0
- package/src/service.ts +285 -0
- package/src/strategy/BaseStrategy.ts +553 -0
- package/src/strategy/CollateralDeficitStrategy.test.ts +728 -0
- package/src/strategy/CollateralDeficitStrategy.ts +421 -0
- package/src/strategy/CompositeStrategy.test.ts +418 -0
- package/src/strategy/CompositeStrategy.ts +102 -0
- package/src/strategy/MinAmountStrategy.test.ts +732 -0
- package/src/strategy/MinAmountStrategy.ts +200 -0
- package/src/strategy/StrategyFactory.test.ts +108 -0
- package/src/strategy/StrategyFactory.ts +157 -0
- package/src/strategy/WeightedStrategy.test.ts +529 -0
- package/src/strategy/WeightedStrategy.ts +126 -0
- package/src/strategy/index.ts +6 -0
- package/src/test/helpers.ts +477 -0
- package/src/test/lifiMocks.ts +211 -0
- package/src/tracking/ActionTracker.test.ts +1625 -0
- package/src/tracking/ActionTracker.ts +1019 -0
- package/src/tracking/IActionTracker.ts +213 -0
- package/src/tracking/InflightContextAdapter.test.ts +206 -0
- package/src/tracking/InflightContextAdapter.ts +75 -0
- package/src/tracking/store/IStore.ts +48 -0
- package/src/tracking/store/InMemoryStore.test.ts +338 -0
- package/src/tracking/store/InMemoryStore.ts +59 -0
- package/src/tracking/store/index.ts +2 -0
- package/src/tracking/types.ts +118 -0
- package/src/utils/ExplorerClient.test.ts +386 -0
- package/src/utils/ExplorerClient.ts +439 -0
- package/src/utils/balanceUtils.test.ts +79 -0
- package/src/utils/balanceUtils.ts +65 -0
- package/src/utils/blockTag.ts +68 -0
- package/src/utils/bridgeUtils.test.ts +193 -0
- package/src/utils/bridgeUtils.ts +101 -0
- package/src/utils/errors.ts +5 -0
- package/src/utils/gasEstimation.ts +306 -0
- package/src/utils/solanaKeyParser.test.ts +103 -0
- package/src/utils/solanaKeyParser.ts +117 -0
- package/src/utils/tokenUtils.ts +89 -0
- package/src/utils/transactionUtils.ts +41 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { ethers, providers } from 'ethers';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ERC20Test__factory,
|
|
5
|
+
HypERC20Collateral__factory,
|
|
6
|
+
} from '@humanode-hyperlane/core';
|
|
7
|
+
|
|
8
|
+
import { ExecutionType, ExternalBridgeType } from '../../config/types.js';
|
|
9
|
+
import {
|
|
10
|
+
type Erc20InventoryChainDeployment,
|
|
11
|
+
type Erc20InventoryDeployedAddresses,
|
|
12
|
+
TEST_CHAIN_CONFIGS,
|
|
13
|
+
type TestChain,
|
|
14
|
+
} from '../fixtures/routes.js';
|
|
15
|
+
|
|
16
|
+
import { BaseLocalDeploymentManager } from './BaseLocalDeploymentManager.js';
|
|
17
|
+
|
|
18
|
+
const TOKEN_SCALE = ethers.BigNumber.from(1);
|
|
19
|
+
const USDC_INITIAL_SUPPLY = '100000000000000';
|
|
20
|
+
const USDC_DECIMALS = 6;
|
|
21
|
+
const INVENTORY_INITIAL_ETH_BALANCE = '20000000000000000000';
|
|
22
|
+
const INVENTORY_INITIAL_ERC20_BALANCE = '20000000000';
|
|
23
|
+
const INVENTORY_ERC20_BRIDGE_SEED = '10000000000';
|
|
24
|
+
|
|
25
|
+
export const MIXED_MOVABLE_CHAINS: readonly TestChain[] = ['anvil1', 'anvil2'];
|
|
26
|
+
export const MIXED_INVENTORY_CHAIN: TestChain = 'anvil3';
|
|
27
|
+
|
|
28
|
+
export const MIXED_INVENTORY_OVERRIDE = {
|
|
29
|
+
executionType: ExecutionType.Inventory,
|
|
30
|
+
externalBridge: ExternalBridgeType.LiFi,
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
export class MixedLocalDeploymentManager extends BaseLocalDeploymentManager<Erc20InventoryDeployedAddresses> {
|
|
34
|
+
constructor(private readonly inventorySignerAddress: string) {
|
|
35
|
+
super();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected async deployRoutes(
|
|
39
|
+
deployerWallet: ethers.Wallet,
|
|
40
|
+
providersByChain: Map<string, providers.JsonRpcProvider>,
|
|
41
|
+
chainInfra: Record<
|
|
42
|
+
string,
|
|
43
|
+
{ mailbox: string; ism: string; merkleHook: string }
|
|
44
|
+
>,
|
|
45
|
+
): Promise<Erc20InventoryDeployedAddresses> {
|
|
46
|
+
const deployerAddress = deployerWallet.address;
|
|
47
|
+
const chainDeployments = {} as Record<
|
|
48
|
+
TestChain,
|
|
49
|
+
Erc20InventoryChainDeployment
|
|
50
|
+
>;
|
|
51
|
+
const monitoredRouters = {} as Record<TestChain, ethers.Contract>;
|
|
52
|
+
const bridgeRouters = {} as Record<TestChain, ethers.Contract>;
|
|
53
|
+
const tokens = {} as Record<TestChain, ethers.Contract>;
|
|
54
|
+
|
|
55
|
+
for (const config of TEST_CHAIN_CONFIGS) {
|
|
56
|
+
const provider = providersByChain.get(config.name)!;
|
|
57
|
+
await provider.send('anvil_setBalance', [
|
|
58
|
+
this.inventorySignerAddress,
|
|
59
|
+
ethers.utils.hexValue(
|
|
60
|
+
ethers.BigNumber.from(INVENTORY_INITIAL_ETH_BALANCE),
|
|
61
|
+
),
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const deployer = deployerWallet.connect(provider);
|
|
65
|
+
|
|
66
|
+
const token = await new ERC20Test__factory(deployer).deploy(
|
|
67
|
+
'USDC',
|
|
68
|
+
'USDC',
|
|
69
|
+
USDC_INITIAL_SUPPLY,
|
|
70
|
+
USDC_DECIMALS,
|
|
71
|
+
);
|
|
72
|
+
await token.deployed();
|
|
73
|
+
|
|
74
|
+
const monitoredRoute = await new HypERC20Collateral__factory(
|
|
75
|
+
deployer,
|
|
76
|
+
).deploy(
|
|
77
|
+
token.address,
|
|
78
|
+
TOKEN_SCALE,
|
|
79
|
+
TOKEN_SCALE,
|
|
80
|
+
chainInfra[config.name].mailbox,
|
|
81
|
+
);
|
|
82
|
+
await monitoredRoute.deployed();
|
|
83
|
+
await monitoredRoute.initialize(
|
|
84
|
+
ethers.constants.AddressZero,
|
|
85
|
+
chainInfra[config.name].ism,
|
|
86
|
+
deployerAddress,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const bridgeRoute = await new HypERC20Collateral__factory(
|
|
90
|
+
deployer,
|
|
91
|
+
).deploy(
|
|
92
|
+
token.address,
|
|
93
|
+
TOKEN_SCALE,
|
|
94
|
+
TOKEN_SCALE,
|
|
95
|
+
chainInfra[config.name].mailbox,
|
|
96
|
+
);
|
|
97
|
+
await bridgeRoute.deployed();
|
|
98
|
+
await bridgeRoute.initialize(
|
|
99
|
+
ethers.constants.AddressZero,
|
|
100
|
+
chainInfra[config.name].ism,
|
|
101
|
+
deployerAddress,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
chainDeployments[config.name] = {
|
|
105
|
+
mailbox: chainInfra[config.name].mailbox,
|
|
106
|
+
ism: chainInfra[config.name].ism,
|
|
107
|
+
monitoredRouter: monitoredRoute.address,
|
|
108
|
+
bridgeRouter: bridgeRoute.address,
|
|
109
|
+
token: token.address,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
tokens[config.name] = token;
|
|
113
|
+
monitoredRouters[config.name] = monitoredRoute;
|
|
114
|
+
bridgeRouters[config.name] = bridgeRoute;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const routeGroups = [monitoredRouters, bridgeRouters];
|
|
118
|
+
for (const routeMap of routeGroups) {
|
|
119
|
+
for (const chain of TEST_CHAIN_CONFIGS) {
|
|
120
|
+
const localRoute = routeMap[chain.name];
|
|
121
|
+
const remoteDomains: number[] = [];
|
|
122
|
+
const remoteRouters: string[] = [];
|
|
123
|
+
|
|
124
|
+
for (const remote of TEST_CHAIN_CONFIGS) {
|
|
125
|
+
if (remote.name === chain.name) continue;
|
|
126
|
+
remoteDomains.push(remote.domainId);
|
|
127
|
+
remoteRouters.push(
|
|
128
|
+
ethers.utils.hexZeroPad(routeMap[remote.name].address, 32),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await localRoute.enrollRemoteRouters(remoteDomains, remoteRouters);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (const chain of TEST_CHAIN_CONFIGS) {
|
|
137
|
+
const monitoredRoute = monitoredRouters[chain.name];
|
|
138
|
+
await monitoredRoute.addRebalancer(deployerAddress);
|
|
139
|
+
if (chain.name === MIXED_INVENTORY_CHAIN) {
|
|
140
|
+
await monitoredRoute.addRebalancer(this.inventorySignerAddress);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const destination of TEST_CHAIN_CONFIGS) {
|
|
144
|
+
if (destination.name === chain.name) continue;
|
|
145
|
+
await monitoredRoute.addBridge(
|
|
146
|
+
destination.domainId,
|
|
147
|
+
bridgeRouters[chain.name].address,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const bridgeSeedAmount = ethers.BigNumber.from(INVENTORY_ERC20_BRIDGE_SEED);
|
|
153
|
+
const signerErc20Amount = ethers.BigNumber.from(
|
|
154
|
+
INVENTORY_INITIAL_ERC20_BALANCE,
|
|
155
|
+
);
|
|
156
|
+
for (const chain of TEST_CHAIN_CONFIGS) {
|
|
157
|
+
const provider = providersByChain.get(chain.name)!;
|
|
158
|
+
const deployer = deployerWallet.connect(provider);
|
|
159
|
+
const token = ERC20Test__factory.connect(
|
|
160
|
+
tokens[chain.name].address,
|
|
161
|
+
deployer,
|
|
162
|
+
);
|
|
163
|
+
const tx1 = await token.transfer(
|
|
164
|
+
bridgeRouters[chain.name].address,
|
|
165
|
+
bridgeSeedAmount,
|
|
166
|
+
);
|
|
167
|
+
await tx1.wait();
|
|
168
|
+
const tx2 = await token.transfer(
|
|
169
|
+
this.inventorySignerAddress,
|
|
170
|
+
signerErc20Amount,
|
|
171
|
+
);
|
|
172
|
+
await tx2.wait();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
chains: chainDeployments,
|
|
177
|
+
monitoredRoute: {
|
|
178
|
+
anvil1: monitoredRouters.anvil1.address,
|
|
179
|
+
anvil2: monitoredRouters.anvil2.address,
|
|
180
|
+
anvil3: monitoredRouters.anvil3.address,
|
|
181
|
+
},
|
|
182
|
+
bridgeRoute: {
|
|
183
|
+
anvil1: bridgeRouters.anvil1.address,
|
|
184
|
+
anvil2: bridgeRouters.anvil2.address,
|
|
185
|
+
anvil3: bridgeRouters.anvil3.address,
|
|
186
|
+
},
|
|
187
|
+
tokens: {
|
|
188
|
+
anvil1: tokens.anvil1.address,
|
|
189
|
+
anvil2: tokens.anvil2.address,
|
|
190
|
+
anvil3: tokens.anvil3.address,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default MixedLocalDeploymentManager;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
|
|
3
|
+
import type { ConfirmedBlockTags } from '../../interfaces/IMonitor.js';
|
|
4
|
+
import type {
|
|
5
|
+
ExplorerMessage,
|
|
6
|
+
IExplorerClient,
|
|
7
|
+
RebalanceActionQueryParams,
|
|
8
|
+
UserTransferQueryParams,
|
|
9
|
+
} from '../../utils/ExplorerClient.js';
|
|
10
|
+
|
|
11
|
+
import type { ForkIndexer } from './ForkIndexer.js';
|
|
12
|
+
|
|
13
|
+
export interface MockExplorerConfig {
|
|
14
|
+
userTransfers?: ExplorerMessage[];
|
|
15
|
+
rebalanceActions?: ExplorerMessage[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class MockExplorerClient implements IExplorerClient {
|
|
19
|
+
private userTransfers: ExplorerMessage[];
|
|
20
|
+
private rebalanceActions: ExplorerMessage[];
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
config: MockExplorerConfig = {},
|
|
24
|
+
private readonly forkIndexer?: ForkIndexer,
|
|
25
|
+
private readonly getBlockTags?: () => Promise<ConfirmedBlockTags>,
|
|
26
|
+
) {
|
|
27
|
+
this.userTransfers = config.userTransfers ?? [];
|
|
28
|
+
this.rebalanceActions = config.rebalanceActions ?? [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getInflightUserTransfers(
|
|
32
|
+
_params: UserTransferQueryParams,
|
|
33
|
+
_logger?: Logger,
|
|
34
|
+
): Promise<ExplorerMessage[]> {
|
|
35
|
+
if (this.forkIndexer && this.getBlockTags) {
|
|
36
|
+
await this.forkIndexer.sync(await this.getBlockTags());
|
|
37
|
+
const indexedTransfers = this.forkIndexer
|
|
38
|
+
.getUserTransfers()
|
|
39
|
+
.filter((msg) => !msg.is_delivered);
|
|
40
|
+
const configTransfers = this.userTransfers.filter(
|
|
41
|
+
(msg) => !msg.is_delivered,
|
|
42
|
+
);
|
|
43
|
+
return [...configTransfers, ...indexedTransfers];
|
|
44
|
+
}
|
|
45
|
+
return this.userTransfers.filter((msg) => !msg.is_delivered);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getInflightRebalanceActions(
|
|
49
|
+
_params: RebalanceActionQueryParams,
|
|
50
|
+
_logger?: Logger,
|
|
51
|
+
): Promise<ExplorerMessage[]> {
|
|
52
|
+
if (this.forkIndexer && this.getBlockTags) {
|
|
53
|
+
await this.forkIndexer.sync(await this.getBlockTags());
|
|
54
|
+
const indexedActions = this.forkIndexer
|
|
55
|
+
.getRebalanceActions()
|
|
56
|
+
.filter((msg) => !msg.is_delivered);
|
|
57
|
+
const configActions = this.rebalanceActions.filter(
|
|
58
|
+
(msg) => !msg.is_delivered,
|
|
59
|
+
);
|
|
60
|
+
return [...configActions, ...indexedActions];
|
|
61
|
+
}
|
|
62
|
+
return this.rebalanceActions.filter((msg) => !msg.is_delivered);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
addUserTransfer(transfer: ExplorerMessage): void {
|
|
66
|
+
this.userTransfers.push(transfer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
addRebalanceAction(action: ExplorerMessage): void {
|
|
70
|
+
this.rebalanceActions.push(action);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
updateTransfer(messageId: string, updates: Partial<ExplorerMessage>): void {
|
|
74
|
+
const transfer = this.userTransfers.find((t) => t.msg_id === messageId);
|
|
75
|
+
if (transfer) {
|
|
76
|
+
Object.assign(transfer, updates);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
updateRebalanceAction(
|
|
81
|
+
messageId: string,
|
|
82
|
+
updates: Partial<ExplorerMessage>,
|
|
83
|
+
): void {
|
|
84
|
+
const action = this.rebalanceActions.find((a) => a.msg_id === messageId);
|
|
85
|
+
if (action) {
|
|
86
|
+
Object.assign(action, updates);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
clearAll(): void {
|
|
91
|
+
this.userTransfers.length = 0;
|
|
92
|
+
this.rebalanceActions.length = 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { BigNumber, ethers, type providers } from 'ethers';
|
|
2
|
+
import { pino, type Logger } from 'pino';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ERC20Test__factory,
|
|
6
|
+
HypERC20Collateral__factory,
|
|
7
|
+
HypNative__factory,
|
|
8
|
+
} from '@humanode-hyperlane/core';
|
|
9
|
+
import { HyperlaneRelayer } from '@humanode-hyperlane/relayer';
|
|
10
|
+
import { HyperlaneCore, type MultiProvider } from '@humanode-hyperlane/sdk';
|
|
11
|
+
import { assert, ProtocolType } from '@humanode-hyperlane/utils';
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
BridgeQuote,
|
|
15
|
+
BridgeQuoteParams,
|
|
16
|
+
BridgeTransferResult,
|
|
17
|
+
BridgeTransferStatus,
|
|
18
|
+
IExternalBridge,
|
|
19
|
+
} from '../../interfaces/IExternalBridge.js';
|
|
20
|
+
import type {
|
|
21
|
+
Erc20InventoryDeployedAddresses,
|
|
22
|
+
NativeDeployedAddresses,
|
|
23
|
+
TestChain,
|
|
24
|
+
} from '../fixtures/routes.js';
|
|
25
|
+
|
|
26
|
+
type MockBridgeRoute = {
|
|
27
|
+
fromChain: number;
|
|
28
|
+
toChain: number;
|
|
29
|
+
fromAddress: string;
|
|
30
|
+
toAddress: string;
|
|
31
|
+
tokenType: 'native' | 'erc20';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export class MockExternalBridge implements IExternalBridge {
|
|
35
|
+
readonly externalBridgeId = 'mock-bridge';
|
|
36
|
+
readonly logger: Logger;
|
|
37
|
+
|
|
38
|
+
private readonly failStatusOverrides = new Map<
|
|
39
|
+
string,
|
|
40
|
+
BridgeTransferStatus
|
|
41
|
+
>();
|
|
42
|
+
private _failNextExecute = false;
|
|
43
|
+
private readonly deployedAddresses:
|
|
44
|
+
| NativeDeployedAddresses
|
|
45
|
+
| Erc20InventoryDeployedAddresses;
|
|
46
|
+
private readonly tokenType: 'native' | 'erc20';
|
|
47
|
+
|
|
48
|
+
constructor(
|
|
49
|
+
deployedAddresses:
|
|
50
|
+
| NativeDeployedAddresses
|
|
51
|
+
| Erc20InventoryDeployedAddresses,
|
|
52
|
+
private readonly multiProvider: MultiProvider,
|
|
53
|
+
private readonly core: HyperlaneCore,
|
|
54
|
+
tokenType: 'native' | 'erc20' = 'native',
|
|
55
|
+
logger?: Logger,
|
|
56
|
+
) {
|
|
57
|
+
this.deployedAddresses = deployedAddresses;
|
|
58
|
+
this.tokenType = tokenType;
|
|
59
|
+
this.logger =
|
|
60
|
+
logger ??
|
|
61
|
+
pino({ level: 'silent' }).child({
|
|
62
|
+
module: 'MockExternalBridge',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getNativeTokenAddress(): string {
|
|
67
|
+
return '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async quote(params: BridgeQuoteParams): Promise<BridgeQuote> {
|
|
71
|
+
if (params.fromAmount !== undefined && params.toAmount !== undefined) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'Cannot specify both fromAmount and toAmount - provide exactly one',
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if (params.fromAmount === undefined && params.toAmount === undefined) {
|
|
77
|
+
throw new Error('Must specify either fromAmount or toAmount');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const amount = params.fromAmount ?? params.toAmount!;
|
|
81
|
+
const toAddress = params.toAddress ?? params.fromAddress;
|
|
82
|
+
|
|
83
|
+
const gasCosts = await this.estimateGasCosts(
|
|
84
|
+
params.fromChain,
|
|
85
|
+
params.toChain,
|
|
86
|
+
toAddress,
|
|
87
|
+
params.fromAddress,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const route: MockBridgeRoute = {
|
|
91
|
+
fromChain: params.fromChain,
|
|
92
|
+
toChain: params.toChain,
|
|
93
|
+
fromAddress: params.fromAddress,
|
|
94
|
+
toAddress,
|
|
95
|
+
tokenType: this.tokenType,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
id: `mock-quote-${Date.now()}`,
|
|
100
|
+
tool: this.externalBridgeId,
|
|
101
|
+
fromAmount: amount,
|
|
102
|
+
toAmount: amount,
|
|
103
|
+
toAmountMin: amount,
|
|
104
|
+
executionDuration: 1,
|
|
105
|
+
gasCosts,
|
|
106
|
+
feeCosts: 0n,
|
|
107
|
+
route,
|
|
108
|
+
requestParams: params,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async execute(
|
|
113
|
+
quote: BridgeQuote,
|
|
114
|
+
privateKeys: Partial<Record<ProtocolType, string>>,
|
|
115
|
+
): Promise<BridgeTransferResult> {
|
|
116
|
+
if (this._failNextExecute) {
|
|
117
|
+
this._failNextExecute = false;
|
|
118
|
+
throw new Error('MockExternalBridge execute failure injected');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const route = this.parseRoute(quote.route);
|
|
122
|
+
const fromChain = route.fromChain;
|
|
123
|
+
const toChain = route.toChain;
|
|
124
|
+
|
|
125
|
+
const fromChainName = this.resolveChainName(fromChain);
|
|
126
|
+
const toChainName = this.resolveChainName(toChain);
|
|
127
|
+
|
|
128
|
+
const bridgeRouteAddress =
|
|
129
|
+
this.deployedAddresses.bridgeRoute[fromChainName];
|
|
130
|
+
const destinationDomain = this.multiProvider.getDomainId(toChainName);
|
|
131
|
+
|
|
132
|
+
const provider = this.multiProvider.getProvider(fromChainName);
|
|
133
|
+
const evmKey = privateKeys[ProtocolType.Ethereum];
|
|
134
|
+
assert(evmKey, 'Missing Ethereum private key for MockExternalBridge');
|
|
135
|
+
const signer = new ethers.Wallet(evmKey, provider);
|
|
136
|
+
|
|
137
|
+
const recipientBytes32 = ethers.utils.hexZeroPad(
|
|
138
|
+
ethers.utils.hexlify(route.toAddress),
|
|
139
|
+
32,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
let tx;
|
|
143
|
+
if (this.tokenType === 'erc20') {
|
|
144
|
+
assert(
|
|
145
|
+
'tokens' in this.deployedAddresses,
|
|
146
|
+
'Expected ERC20 deployed addresses',
|
|
147
|
+
);
|
|
148
|
+
const tokenAddress = (
|
|
149
|
+
this.deployedAddresses as Erc20InventoryDeployedAddresses
|
|
150
|
+
).tokens[fromChainName];
|
|
151
|
+
const token = ERC20Test__factory.connect(tokenAddress, signer);
|
|
152
|
+
await token.approve(bridgeRouteAddress, quote.fromAmount);
|
|
153
|
+
|
|
154
|
+
const bridgeRoute = HypERC20Collateral__factory.connect(
|
|
155
|
+
bridgeRouteAddress,
|
|
156
|
+
signer,
|
|
157
|
+
);
|
|
158
|
+
tx = await bridgeRoute.transferRemote(
|
|
159
|
+
destinationDomain,
|
|
160
|
+
recipientBytes32,
|
|
161
|
+
quote.fromAmount,
|
|
162
|
+
);
|
|
163
|
+
} else {
|
|
164
|
+
const bridgeRoute = HypNative__factory.connect(
|
|
165
|
+
bridgeRouteAddress,
|
|
166
|
+
signer,
|
|
167
|
+
);
|
|
168
|
+
tx = await bridgeRoute.transferRemote(
|
|
169
|
+
destinationDomain,
|
|
170
|
+
recipientBytes32,
|
|
171
|
+
quote.fromAmount,
|
|
172
|
+
{ value: quote.fromAmount },
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Wait for the transaction to be mined so that getStatus() can always
|
|
177
|
+
// find the receipt via getTransactionReceipt(). Without this, there is
|
|
178
|
+
// a race on automined anvil where the receipt is not yet available.
|
|
179
|
+
await tx.wait();
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
txHash: tx.hash,
|
|
183
|
+
fromChain,
|
|
184
|
+
toChain,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async getStatus(
|
|
189
|
+
txHash: string,
|
|
190
|
+
fromChain: number,
|
|
191
|
+
toChain: number,
|
|
192
|
+
): Promise<BridgeTransferStatus> {
|
|
193
|
+
const override = this.failStatusOverrides.get(txHash);
|
|
194
|
+
if (override) {
|
|
195
|
+
return override;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const fromChainName = this.resolveChainName(fromChain);
|
|
200
|
+
const toChainName = this.resolveChainName(toChain);
|
|
201
|
+
const provider = this.multiProvider.getProvider(fromChainName);
|
|
202
|
+
const dispatchTxReceipt = await provider.getTransactionReceipt(txHash);
|
|
203
|
+
|
|
204
|
+
if (!dispatchTxReceipt) {
|
|
205
|
+
return { status: 'not_found' };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const dispatchedMessages =
|
|
209
|
+
HyperlaneCore.getDispatchedMessages(dispatchTxReceipt);
|
|
210
|
+
assert(
|
|
211
|
+
dispatchedMessages.length === 1,
|
|
212
|
+
`Expected exactly 1 dispatched message, got ${dispatchedMessages.length} for tx ${txHash}`,
|
|
213
|
+
);
|
|
214
|
+
const dispatchedMsgId = dispatchedMessages[0].id;
|
|
215
|
+
|
|
216
|
+
const relayer = new HyperlaneRelayer({ core: this.core });
|
|
217
|
+
const receipts = await relayer.relayAll(dispatchTxReceipt);
|
|
218
|
+
|
|
219
|
+
const destinationDomain = this.multiProvider.getDomainId(toChainName);
|
|
220
|
+
const destinationReceipts =
|
|
221
|
+
receipts[toChainName] ??
|
|
222
|
+
receipts[toChain] ??
|
|
223
|
+
receipts[destinationDomain];
|
|
224
|
+
|
|
225
|
+
// If relayAll didn't produce receipts (e.g. message already delivered),
|
|
226
|
+
// fall back to checking on-chain delivery status directly.
|
|
227
|
+
if (!destinationReceipts || destinationReceipts.length === 0) {
|
|
228
|
+
const destMailbox = this.core.getContracts(toChainName).mailbox;
|
|
229
|
+
const isDelivered = await destMailbox.delivered(dispatchedMsgId);
|
|
230
|
+
if (isDelivered) {
|
|
231
|
+
const receivedAmount = await this.getTransferredAmount(
|
|
232
|
+
provider,
|
|
233
|
+
dispatchTxReceipt,
|
|
234
|
+
);
|
|
235
|
+
// Find the actual destination chain process tx
|
|
236
|
+
const processEvents = await destMailbox.queryFilter(
|
|
237
|
+
destMailbox.filters.ProcessId(dispatchedMsgId),
|
|
238
|
+
);
|
|
239
|
+
assert(
|
|
240
|
+
processEvents.length > 0,
|
|
241
|
+
`No ProcessId event found for message ${dispatchedMsgId} on ${toChainName}`,
|
|
242
|
+
);
|
|
243
|
+
return {
|
|
244
|
+
status: 'complete',
|
|
245
|
+
receivingTxHash: processEvents[0].transactionHash,
|
|
246
|
+
receivedAmount,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return { status: 'not_found' };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const receivedAmount = await this.getTransferredAmount(
|
|
253
|
+
provider,
|
|
254
|
+
dispatchTxReceipt,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
status: 'complete',
|
|
259
|
+
receivingTxHash: destinationReceipts[0].transactionHash,
|
|
260
|
+
receivedAmount,
|
|
261
|
+
};
|
|
262
|
+
} catch (error) {
|
|
263
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
264
|
+
return { status: 'failed', error: message };
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
failStatusFor(
|
|
269
|
+
txHash: string,
|
|
270
|
+
status: BridgeTransferStatus = { status: 'failed' },
|
|
271
|
+
): void {
|
|
272
|
+
this.failStatusOverrides.set(txHash, status);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
failNextExecute(): void {
|
|
276
|
+
this._failNextExecute = true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
reset(): void {
|
|
280
|
+
this.failStatusOverrides.clear();
|
|
281
|
+
this._failNextExecute = false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Estimates gas costs for a transferRemote call on the bridge route.
|
|
286
|
+
* Uses a small amount (1 wei) to avoid balance-related estimation failures.
|
|
287
|
+
*/
|
|
288
|
+
private async estimateGasCosts(
|
|
289
|
+
fromChain: number,
|
|
290
|
+
toChain: number,
|
|
291
|
+
toAddress: string,
|
|
292
|
+
fromAddress: string,
|
|
293
|
+
): Promise<bigint> {
|
|
294
|
+
const fromChainName = this.resolveChainName(fromChain);
|
|
295
|
+
const toChainName = this.resolveChainName(toChain);
|
|
296
|
+
|
|
297
|
+
const bridgeRouteAddress =
|
|
298
|
+
this.deployedAddresses.bridgeRoute[fromChainName];
|
|
299
|
+
const destinationDomain = this.multiProvider.getDomainId(toChainName);
|
|
300
|
+
const provider = this.multiProvider.getProvider(fromChainName);
|
|
301
|
+
|
|
302
|
+
const recipientBytes32 = ethers.utils.hexZeroPad(
|
|
303
|
+
ethers.utils.hexlify(toAddress),
|
|
304
|
+
32,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// Use 1 wei for estimation — gas usage doesn't depend on transfer amount
|
|
308
|
+
const estimateAmount = 1n;
|
|
309
|
+
if (this.tokenType === 'erc20') {
|
|
310
|
+
// ERC20 transferRemote requires token approval which isn't set up during estimation.
|
|
311
|
+
// Return 0n as a mock — gas costs don't affect test logic.
|
|
312
|
+
return 0n;
|
|
313
|
+
} else {
|
|
314
|
+
const bridgeRoute = HypNative__factory.connect(
|
|
315
|
+
bridgeRouteAddress,
|
|
316
|
+
provider,
|
|
317
|
+
);
|
|
318
|
+
const gasEstimate = await bridgeRoute.estimateGas.transferRemote(
|
|
319
|
+
destinationDomain,
|
|
320
|
+
recipientBytes32,
|
|
321
|
+
estimateAmount,
|
|
322
|
+
{ value: estimateAmount, from: fromAddress },
|
|
323
|
+
);
|
|
324
|
+
const gasPrice = await provider.getGasPrice();
|
|
325
|
+
return gasEstimate.mul(gasPrice).toBigInt();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private parseRoute(route: unknown): MockBridgeRoute {
|
|
330
|
+
if (!route || typeof route !== 'object') {
|
|
331
|
+
throw new Error('Mock quote route is missing');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const parsed = route as Partial<MockBridgeRoute>;
|
|
335
|
+
|
|
336
|
+
if (
|
|
337
|
+
typeof parsed.fromChain !== 'number' ||
|
|
338
|
+
typeof parsed.toChain !== 'number' ||
|
|
339
|
+
typeof parsed.fromAddress !== 'string' ||
|
|
340
|
+
typeof parsed.toAddress !== 'string' ||
|
|
341
|
+
(parsed.tokenType !== 'native' && parsed.tokenType !== 'erc20')
|
|
342
|
+
) {
|
|
343
|
+
throw new Error('Mock quote route is invalid');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
fromChain: parsed.fromChain,
|
|
348
|
+
toChain: parsed.toChain,
|
|
349
|
+
fromAddress: parsed.fromAddress,
|
|
350
|
+
toAddress: parsed.toAddress,
|
|
351
|
+
tokenType: parsed.tokenType,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private resolveChainName(chainRef: number): TestChain {
|
|
356
|
+
const chainNames = Object.keys(
|
|
357
|
+
this.deployedAddresses.chains,
|
|
358
|
+
) as TestChain[];
|
|
359
|
+
|
|
360
|
+
for (const chainName of chainNames) {
|
|
361
|
+
const chainId = Number(this.multiProvider.getChainId(chainName));
|
|
362
|
+
const domainId = this.multiProvider.getDomainId(chainName);
|
|
363
|
+
if (chainId === chainRef || domainId === chainRef) {
|
|
364
|
+
return chainName;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
throw new Error(`Chain not found for id/domain ${chainRef}`);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private async getTransferredAmount(
|
|
372
|
+
provider: providers.Provider,
|
|
373
|
+
receipt: providers.TransactionReceipt,
|
|
374
|
+
): Promise<bigint> {
|
|
375
|
+
const tx = await provider.getTransaction(receipt.transactionHash);
|
|
376
|
+
if (!tx) {
|
|
377
|
+
throw new Error(
|
|
378
|
+
`Transaction ${receipt.transactionHash} not found on provider`,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
const parsed = HypNative__factory.createInterface().parseTransaction({
|
|
384
|
+
data: tx.data,
|
|
385
|
+
value: tx.value,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
if (!parsed || parsed.name !== 'transferRemote') {
|
|
389
|
+
throw new Error(
|
|
390
|
+
`Expected transferRemote tx, got: ${parsed?.name ?? 'unparseable'}`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const amount = parsed.args[2];
|
|
395
|
+
if (BigNumber.isBigNumber(amount)) {
|
|
396
|
+
return amount.toBigInt();
|
|
397
|
+
}
|
|
398
|
+
if (typeof amount === 'bigint') {
|
|
399
|
+
return amount;
|
|
400
|
+
}
|
|
401
|
+
return BigInt(String(amount));
|
|
402
|
+
} catch (error: unknown) {
|
|
403
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
404
|
+
this.logger.warn(
|
|
405
|
+
{ txHash: receipt.transactionHash, error: message },
|
|
406
|
+
'Failed to parse transferRemote amount from tx',
|
|
407
|
+
);
|
|
408
|
+
throw new Error(`Failed to parse transferred amount: ${message}`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|