@hyperlane-xyz/rebalancer
v27.1.0
Published
Hyperlane Warp Route Collateral Rebalancer Service
Downloads
2,349
Readme
@hyperlane-xyz/rebalancer
Hyperlane Warp Route Collateral Rebalancer Service - maintains optimal collateral distribution across chains for Hyperlane warp routes.
Overview
The rebalancer monitors collateral balances across warp route deployments and automatically transfers tokens between chains to maintain configured target balances. It supports both manual one-off rebalances and continuous daemon mode for production deployments.
Features
- Multi-Protocol Support: Protocol-agnostic design supporting EVM chains (Cosmos, Sealevel, etc. when movable collateral contracts available)
- Flexible Strategies: Weighted, minimum-amount, and collateral-deficit rebalancing strategies
- Composite Strategies: Combine multiple strategies with different bridges for layered rebalancing
- Inflight Tracking: Monitors pending rebalances to prevent duplicate transfers
- Safety Features: Inflight message tracking and comprehensive validation
- Observability: Built-in Prometheus metrics and structured logging
- Dual Mode: Manual CLI execution or continuous daemon service
- Bridge Support: Integration with Hyperlane warp routes and external bridges
Installation
# From monorepo root
pnpm install
# Build the package
pnpm --filter @hyperlane-xyz/rebalancer buildUsage
Manual Rebalancing (CLI)
Execute a one-off rebalance using the CLI:
# Via CLI package
pnpm --filter @hyperlane-xyz/cli hyperlane warp rebalancer \
--config /path/to/rebalancer-config.yaml \
--manual \
--origin ethereum \
--destination arbitrum \
--amount 1000Daemon Mode (Service)
Run as a continuous service (typically in K8s):
# Set environment variables
export REBALANCER_CONFIG_FILE=/path/to/rebalancer-config.yaml
export HYP_KEY=your_private_key
export COINGECKO_API_KEY=your_api_key
# Start the service
pnpm --filter @hyperlane-xyz/rebalancer start
# Or with direct node
node dist/service.jsProgrammatic Usage
import { RebalancerService } from '@hyperlane-xyz/rebalancer';
const service = new RebalancerService(
multiProvider,
multiProtocolProvider,
registry,
rebalancerConfig,
{
mode: 'daemon',
checkFrequency: 60_000,
withMetrics: true,
coingeckoApiKey: process.env.COINGECKO_API_KEY,
logger: console,
},
);
// Start daemon
await service.start();
// Or execute manual rebalance
await service.executeManual({
origin: 'ethereum',
destination: 'arbitrum',
amount: '1000',
});Configuration
The rebalancer uses a YAML configuration file with a warpRouteId and strategy field.
Basic Example (Single Strategy)
warpRouteId: ETH/ethereum-arbitrum-optimism
strategy:
rebalanceStrategy: weighted
chains:
ethereum:
weight: 60
tolerance: 5
bridge: '0x1234...abcd'
arbitrum:
weight: 20
tolerance: 5
bridge: '0x5678...efgh'Composite Strategy (v1.0.0+)
The strategy field accepts an array of strategies for composite rebalancing. Strategies are evaluated in order - the first strategy that produces routes is used.
warpRouteId: USDC/base-ethereum-arbitrum
strategy:
# First: CollateralDeficitStrategy with fast bridges for reactive rebalancing
- rebalanceStrategy: collateralDeficit
chains:
base:
buffer: 0
bridge: '0x584244d02b0fBf9054A5D5C9e9cE9A2E8adA0e28'
ethereum:
buffer: 0
bridge: '0xEE4a09db2C25592C04b8b342CB89f9a7f5E20BD2'
# Second: MinAmountStrategy with standard bridges for baseline floors
- rebalanceStrategy: minAmount
chains:
base:
minAmount:
min: 0.1
target: 0.11
type: 'absolute'
bridgeLockTime: 1800
bridge: '0x33e94B6D2ae697c16a750dB7c3d9443622C4405a'
ethereum:
minAmount:
min: 0.1
target: 0.11
type: 'absolute'
bridgeLockTime: 1800
bridge: '0x8c8D831E1e879604b4B304a2c951B8AEe3aB3a23'Note: When using
collateralDeficitin a composite strategy, it must be the first strategy in the array.
Strategy Types
| Strategy | Use Case | Chain Config Fields |
| ------------------- | ------------------------------------------------------ | -------------------------------- |
| weighted | Maintain percentage distribution across chains | weight, tolerance |
| minAmount | Trigger rebalance when balance falls below floor | minAmount: {min, target, type} |
| collateralDeficit | React to bridged supply gaps (synthetic vs collateral) | buffer |
Weighted Strategy
Maintains target weight percentages across chains. Rebalances when deviation exceeds tolerance.
strategy:
rebalanceStrategy: weighted
chains:
ethereum:
weight: 60 # Target 60% of total supply
tolerance: 5 # Rebalance if >5% deviation
bridge: '0x...'MinAmount Strategy
Triggers rebalance when a chain's balance falls below the minimum threshold.
strategy:
rebalanceStrategy: minAmount
chains:
ethereum:
minAmount:
min: 100 # Trigger rebalance below this
target: 110 # Rebalance up to this amount
type: 'absolute' # or 'relative' (percentage of total)
bridge: '0x...'CollateralDeficit Strategy
Monitors bridged (synthetic) supply vs collateral and rebalances to cover deficits.
strategy:
rebalanceStrategy: collateralDeficit
chains:
ethereum:
buffer: 1000 # Extra collateral buffer above deficit
bridge: '0x...'Chain Config Reference
| Field | Type | Required | Description |
| ------------------------- | ---------------- | -------- | -------------------------------------------------------------- |
| bridge | 0x... address | Yes | Bridge contract address for this chain |
| bridgeLockTime | number (seconds) | No | Expected bridge transfer duration (used for inflight tracking) |
| bridgeMinAcceptedAmount | number | No | Skip routes with amounts below this threshold |
| override | object | No | Per-destination bridge overrides (see below) |
Per-Destination Overrides
Use override to specify different bridge configs for specific destination chains:
strategy:
rebalanceStrategy: minAmount
chains:
ethereum:
minAmount: { min: 100, target: 110, type: 'absolute' }
bridge: '0xDefaultBridge...'
override:
arbitrum:
bridge: '0xFastArbitrumBridge...'
bridgeLockTime: 600
optimism:
bridge: '0xOptimismBridge...'Architecture
Package Structure
typescript/rebalancer/
├── src/
│ ├── core/
│ │ ├── RebalancerService.ts # Main orchestrator
│ │ └── Rebalancer.ts # Core rebalancing logic
│ ├── strategy/
│ │ ├── WeightedStrategy.ts # Weighted distribution
│ │ ├── MinAmountStrategy.ts # Minimum threshold strategy
│ │ ├── CollateralDeficitStrategy.ts # Bridged supply deficit strategy
│ │ └── CompositeStrategy.ts # Combines multiple strategies
│ ├── monitor/
│ │ └── Monitor.ts # Balance monitoring
│ ├── metrics/
│ │ └── Metrics.ts # Prometheus metrics collection
│ ├── config/
│ │ └── RebalancerConfig.ts # Config loading/validation
│ ├── utils/
│ ├── interfaces/
│ ├── service.ts # Service entry point
│ └── index.ts # Public APIDependencies
@hyperlane-xyz/sdk: Core SDK with MultiProvider and WarpCore@hyperlane-xyz/provider-sdk: Protocol-agnostic provider abstractions@hyperlane-xyz/utils: Shared utilities and typesprom-client: Prometheus metricspino: Structured logging
Development
Running Tests
pnpm --filter @hyperlane-xyz/rebalancer testLocal Development
# Watch mode
pnpm --filter @hyperlane-xyz/rebalancer dev
# Start with test config
HYP_KEY=your_test_key \
REBALANCER_CONFIG_FILE=./test-config.yaml \
pnpm --filter @hyperlane-xyz/rebalancer start:devMigration from CLI
This package replaces the rebalancer functionality previously embedded in @hyperlane-xyz/cli. Key changes:
- Dedicated Package: Now a standalone service package
- Direct Entry Point: K8s deployments use
service.tsdirectly (no CLI wrapper) - Metrics Included: Prometheus metrics stay with the service
- Protocol-Agnostic: Aligned with multi-VM architecture
- Dual Mode Support: Single codebase for both manual and daemon modes
License
Apache-2.0
