feat: add standalone warp-monitor package with Docker image#7653
feat: add standalone warp-monitor package with Docker image#7653paulbalaji merged 22 commits intomainfrom
Conversation
- Create new @hyperlane-xyz/warp-monitor package with:
- Service entry point using env vars (WARP_ROUTE_ID, REGISTRY_URI, etc.)
- Prometheus metrics on port 9090
- ncc bundling for minimal Docker image size
- Multi-stage Dockerfile for standalone deployment
- Update Helm chart to use new standalone image:
- Use gcr.io/abacus-labs-dev/hyperlane-warp-monitor
- Configure via REGISTRY_URI with /tree/{commit} format
- Remove args-based script invocation
- Add GitHub Actions workflow for building and pushing images
- Remove old monitor scripts from infra package
- Add @vercel/ncc to pnpm catalog
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add tests for metrics module (updateTokenBalanceMetrics, updateNativeWalletBalanceMetrics, updateXERC20LimitsMetrics) - Add tests for utils module (getLogger, setLoggerBindings, tryFn) - Add tests for types module (type validation) - Add chai, sinon dev dependencies for testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add comprehensive tests for Prometheus metrics recording - Verify metrics include correct labels (chain_name, token_name, etc.) - Test xERC20 limit types and bridge address labels - Remove unused sinon imports - Fix tsconfig.json to include test files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughThis PR consolidates Warp Monitor logic from separate scripts into a unified TypeScript service package with metrics, Kubernetes integration, and Docker containerization. Updates Helm values and infrastructure code to use the new warp-monitor image and registry configuration. Adds CI/CD workflow for building and publishing the Warp Monitor Docker image. Changes
Sequence Diagram(s)sequenceDiagram
participant Service as Warp Monitor<br/>Service
participant Monitor as WarpMonitor<br/>Class
participant Registry as Registry<br/>Fetcher
participant Chain as Chain<br/>Metadata
participant Core as WarpCore
participant Metrics as Metrics<br/>Server
participant CoinGecko as CoinGecko<br/>API
Service->>Service: Parse env (WARP_ROUTE_ID,<br/>CHECK_FREQUENCY, etc.)
Service->>Service: Initialize logger
Service->>Monitor: Create WarpMonitor<br/>(config)
Monitor->>Monitor: start()
Monitor->>Registry: Fetch registry config
Registry-->>Monitor: Chain metadata & addresses
Monitor->>Core: Build WarpCore
Monitor->>Core: Load WarpDeployConfig
rect rgb(100, 150, 200)
Note over Monitor,Metrics: Polling Loop (every checkFrequency ms)
end
loop For each token in WarpRoute
Monitor->>Core: Get token & adapters
Monitor->>Monitor: updateTokenMetrics()
alt EVM Token
Monitor->>Monitor: Get bridged balance
Monitor->>CoinGecko: Fetch token price
CoinGecko-->>Monitor: Price or undefined
end
alt Sealevel Token
Monitor->>Monitor: Get ATA payer balance
end
alt xERC20 Token
Monitor->>Core: Get XERC20 adapter
Monitor->>Monitor: Retrieve limits<br/>(mint/burn/max)
Monitor->>Monitor: Check lockbox collateral
Monitor->>CoinGecko: Price for collateral
CoinGecko-->>Monitor: Collateral value
end
Monitor->>Metrics: Update token balance<br/>gauge
Monitor->>Metrics: Update value@risk<br/>gauge
Monitor->>Metrics: Update limits<br/>gauge (xERC20)
end
Monitor->>Metrics: Poll complete<br/>Metrics exported
Metrics-->>Service: /metrics endpoint
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes The changes introduce a complete new TypeScript service package with intricate monitoring logic, multiple test suites, Docker/Helm infrastructure, and CI/CD workflows. Dense logic in Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (1)typescript/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (5)📓 Common learnings📚 Learning: 2025-12-29T19:45:12.592ZApplied to files:
📚 Learning: 2025-06-16T11:17:55.750ZApplied to files:
📚 Learning: 2025-11-26T13:28:51.658ZApplied to files:
📚 Learning: 2025-08-13T16:53:55.163ZApplied to files:
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (61)
🔇 Additional comments (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
typescript/warp-monitor/src/types.test.ts (1)
1-97: Type tests provide good documentation value.While TypeScript's compiler already validates type conformance, these tests serve as useful living documentation showing how to construct each type. They're particularly helpful for the optional fields examples (lines 26-33, 87-95).
That said, if you're lookin' to trim test execution time down the road, these could be candidates for skipping since the compiler does most of the heavy lifting here.
typescript/warp-monitor/scripts/ncc.post-bundle.mjs (1)
31-36: String manipulation could be more robust.The current approach splits on the shebang string (line 32), which assumes the shebang only appears once at the beginning. If the shebang text somehow appears in the bundled code (unlikely but possible in strings or comments), this could incorrectly split the content.
A safer approach would be to slice based on the shebang length:
🔎 More robust string handling
if (!content.includes(dirnameDef)) { - const [, executable] = content.split(shebang); - const newContent = `${shebang}\n${dirnameDef}\n${executable}`; + const afterShebang = content.slice(shebang.length); + const newContent = `${shebang}\n${dirnameDef}${afterShebang}`; await writeFile(outputFile, newContent, 'utf8'); console.log('Adding missing __dirname definition to service executable'); }This avoids potential issues with the shebang string appearing elsewhere in the bundle.
typescript/warp-monitor/src/service.ts (1)
44-108: Main function is well-structured, like a proper onion with layers.The validation, logging initialization, registry setup, and monitor startup are all nicely organized. Error handling exits with code 1 appropriately.
One thing that might be worth adding down the road - graceful shutdown handling for
SIGTERM/SIGINT. When Kubernetes wants to evict the pod, it'd be nice to let the current metrics update finish before shutting down. Not a blocker though, the service will work fine without it.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (27)
.github/workflows/warp-monitor-docker.yml(1 hunks)Dockerfile(1 hunks)pnpm-workspace.yaml(1 hunks)typescript/cli/package.json(1 hunks)typescript/infra/helm/warp-routes/templates/_helpers.tpl(1 hunks)typescript/infra/helm/warp-routes/values.yaml(1 hunks)typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts(0 hunks)typescript/infra/scripts/warp-routes/monitor/status.ts(0 hunks)typescript/infra/scripts/warp-routes/monitor/utils.ts(0 hunks)typescript/infra/src/warp/helm.ts(3 hunks)typescript/warp-monitor/.gitignore(1 hunks)typescript/warp-monitor/.mocharc.json(1 hunks)typescript/warp-monitor/Dockerfile(1 hunks)typescript/warp-monitor/eslint.config.mjs(1 hunks)typescript/warp-monitor/package.json(1 hunks)typescript/warp-monitor/scripts/ncc.post-bundle.mjs(1 hunks)typescript/warp-monitor/src/index.ts(1 hunks)typescript/warp-monitor/src/metrics.test.ts(1 hunks)typescript/warp-monitor/src/metrics.ts(10 hunks)typescript/warp-monitor/src/monitor.ts(1 hunks)typescript/warp-monitor/src/service.ts(1 hunks)typescript/warp-monitor/src/types.test.ts(1 hunks)typescript/warp-monitor/src/types.ts(2 hunks)typescript/warp-monitor/src/utils.test.ts(1 hunks)typescript/warp-monitor/src/utils.ts(1 hunks)typescript/warp-monitor/tsconfig.json(1 hunks)typescript/warp-monitor/turbo.json(1 hunks)
💤 Files with no reviewable changes (3)
- typescript/infra/scripts/warp-routes/monitor/monitor-warp-route-balances.ts
- typescript/infra/scripts/warp-routes/monitor/status.ts
- typescript/infra/scripts/warp-routes/monitor/utils.ts
🧰 Additional context used
📓 Path-based instructions (1)
typescript/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
typescript/**/*.{ts,tsx}: UseChainMapfor per-chain configurations in TypeScript
Import types from@hyperlane-xyz/sdkwhen using TypeScript SDK types
Files:
typescript/warp-monitor/src/types.test.tstypescript/warp-monitor/src/types.tstypescript/warp-monitor/src/metrics.test.tstypescript/warp-monitor/src/index.tstypescript/warp-monitor/src/service.tstypescript/warp-monitor/src/utils.tstypescript/infra/src/warp/helm.tstypescript/warp-monitor/src/utils.test.tstypescript/warp-monitor/src/monitor.tstypescript/warp-monitor/src/metrics.ts
🧠 Learnings (13)
📚 Learning: 2025-09-05T15:13:08.394Z
Learnt from: ltyu
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6992
File: typescript/sdk/src/token/types.test.ts:188-197
Timestamp: 2025-09-05T15:13:08.394Z
Learning: WarpRouteDeployConfigSchema.safeParse automatically populates missing token fields during preprocessing, so manual specification of top-level token fields in RoutingFee test cases is not necessary.
Applied to files:
typescript/warp-monitor/src/types.test.tstypescript/warp-monitor/src/metrics.ts
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Applies to typescript/**/*.{ts,tsx} : Use `ChainMap` for per-chain configurations in TypeScript
Applied to files:
typescript/warp-monitor/src/types.tstypescript/warp-monitor/tsconfig.jsontypescript/warp-monitor/.mocharc.jsontypescript/warp-monitor/turbo.json
📚 Learning: 2025-06-16T11:17:55.750Z
Learnt from: xeno097
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6486
File: typescript/cli/src/tests/warp/warp-check.e2e-test.ts:490-494
Timestamp: 2025-06-16T11:17:55.750Z
Learning: In the Hyperlane registry, the label part of warp IDs can now be any value that matches the registry's regex requirements, not just actual chain names. This means functions like getCombinedWarpRoutePath can accept descriptive filenames like WARP_DEPLOY_DEFAULT_FILE_NAME as valid label components for constructing registry paths.
Applied to files:
typescript/warp-monitor/src/types.tstypescript/infra/src/warp/helm.tstypescript/infra/helm/warp-routes/templates/_helpers.tpltypescript/infra/helm/warp-routes/values.yaml
📚 Learning: 2025-08-26T13:45:52.227Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/testnet_config.json:34-35
Timestamp: 2025-08-26T13:45:52.227Z
Learning: Skip reviewing mainnet_config.json and testnet_config.json configuration files in typescript/infra/config/ and rust/main/config/ directories as requested by paulbalaji to reduce review noise.
Applied to files:
typescript/warp-monitor/tsconfig.jsontypescript/warp-monitor/.mocharc.jsontypescript/warp-monitor/.gitignoretypescript/warp-monitor/turbo.json
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Applies to typescript/**/*.{ts,tsx} : Import types from `hyperlane-xyz/sdk` when using TypeScript SDK types
Applied to files:
typescript/warp-monitor/tsconfig.jsontypescript/warp-monitor/.mocharc.jsonDockerfiletypescript/warp-monitor/package.json
📚 Learning: 2025-11-25T17:10:33.369Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: solidity/foundry.toml:8-8
Timestamp: 2025-11-25T17:10:33.369Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, when using pnpm (instead of Yarn), Foundry's `allow_paths` in solidity/foundry.toml should be set to `["./node_modules"]` rather than `["../node_modules"]` because pnpm's default node_modules structure places dependencies locally in the workspace subdirectory, not requiring access to the parent directory's node_modules.
Applied to files:
pnpm-workspace.yamltypescript/warp-monitor/Dockerfiletypescript/warp-monitor/package.json
📚 Learning: 2025-07-11T10:06:07.854Z
Learnt from: Mo-Hussain
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6702
File: typescript/utils/src/logging.ts:75-93
Timestamp: 2025-07-11T10:06:07.854Z
Learning: In the hyperlane-xyz/utils package, pino-pretty is added as an optional peer dependency rather than a direct dependency, allowing consuming projects to decide if they want the pretty logging functionality without forcing all consumers to install it.
Applied to files:
typescript/warp-monitor/src/utils.ts
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Most deployments are config-driven; check `typescript/infra/config/` for deployment configuration examples
Applied to files:
Dockerfiletypescript/warp-monitor/turbo.json
📚 Learning: 2025-08-13T16:53:55.163Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6891
File: typescript/infra/config/environments/mainnet3/funding.ts:22-22
Timestamp: 2025-08-13T16:53:55.163Z
Learning: In Hyperlane mainnet3 configs, funding.ts uses 'gcr.io/abacus-labs-dev/hyperlane-monorepo' docker image while agent.ts uses 'gcr.io/abacus-labs-dev/hyperlane-agent' docker image. These are different images with independent tag cycles, so tag consistency across them is not expected.
Applied to files:
typescript/warp-monitor/Dockerfiletypescript/infra/src/warp/helm.tstypescript/infra/helm/warp-routes/values.yaml
📚 Learning: 2025-11-26T13:28:51.658Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: typescript/cli/package.json:20-20
Timestamp: 2025-11-26T13:28:51.658Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, hyperlane-xyz/registry is maintained in a separate repository and published to npm, so it should use a pinned version (e.g., "23.6.0") rather than the workspace protocol ("workspace:*") that other internal Hyperlane packages use.
Applied to files:
typescript/infra/src/warp/helm.tstypescript/warp-monitor/package.jsontypescript/infra/helm/warp-routes/values.yaml
📚 Learning: 2025-09-15T17:15:41.014Z
Learnt from: xeno097
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7034
File: typescript/infra/config/environments/mainnet3/rebalancer/USDC/pulsechain.yaml:0-0
Timestamp: 2025-09-15T17:15:41.014Z
Learning: Bridge addresses for USDC warp routes in pulsechain.yaml configurations should reference the canonical addresses from the hyperlane-registry repo's mainnet-cctp-config.yaml file rather than being generated independently.
Applied to files:
typescript/infra/helm/warp-routes/values.yaml
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Chain metadata lives in external `hyperlane-xyz/registry` package, not in the main repository
Applied to files:
typescript/infra/helm/warp-routes/values.yaml
📚 Learning: 2025-09-18T15:49:20.478Z
Learnt from: yorhodes
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6750
File: solidity/contracts/token/bridge/EverclearTokenBridge.sol:212-212
Timestamp: 2025-09-18T15:49:20.478Z
Learning: EverclearTokenBridge sends funds directly to recipients for ERC20 transfers, while EverclearEthBridge sends funds to remote routers that handle WETH unwrapping and ETH delivery. The virtual _getReceiver and _getIntentCalldata functions enable this architectural difference between the two bridge implementations.
Applied to files:
typescript/warp-monitor/src/metrics.ts
🧬 Code graph analysis (2)
typescript/warp-monitor/src/metrics.test.ts (1)
typescript/sdk/src/index.ts (1)
TokenStandard(732-732)
typescript/warp-monitor/src/utils.ts (1)
typescript/infra/src/infrastructure/monitoring/grafana.ts (1)
logger(14-14)
🔇 Additional comments (37)
typescript/warp-monitor/.mocharc.json (1)
1-3: Standard Mocha configuration looks good.The tsx import enables TypeScript module support for tests, which is exactly what ya need here.
typescript/warp-monitor/tsconfig.json (1)
1-8: TypeScript configuration follows monorepo conventions.Extends the shared config and sets up standard output/source directories. All looks proper.
pnpm-workspace.yaml (1)
97-97: Good move centralizing ncc version in the catalog.This'll keep the version consistent across packages that use ncc for bundling.
typescript/warp-monitor/.gitignore (1)
1-4: Ignore patterns cover the necessary artifacts.Environment files, build outputs, cache, and the ncc bundle are all properly excluded from version control.
typescript/cli/package.json (1)
39-39: Migration to catalog reference is consistent.This aligns with the catalog entry added in pnpm-workspace.yaml, ensuring the CLI uses the same ncc version as other packages.
typescript/warp-monitor/eslint.config.mjs (1)
1-14: ESLint configuration is sensible for a Node.js service.Extending the monorepo defaults and disabling the restricted imports rule makes sense when you're building a standalone Node.js service that needs direct access to built-ins.
typescript/warp-monitor/turbo.json (1)
1-9: Turborepo task configuration is set up properly.The bundle task correctly depends on build and declares its outputs, which'll help Turbo cache things efficiently.
Dockerfile (1)
37-37: Warp-monitor package.json added in the right spot.Follows the same pattern as other packages and maintains alphabetical ordering. This'll let pnpm install the warp-monitor dependencies during the Docker build.
typescript/infra/helm/warp-routes/values.yaml (2)
2-2: Nice upgrade to the standalone image.The switch to the dedicated warp-monitor image makes sense and should significantly reduce the image size (from 6.39 GB to 227 MB as noted in the PR). This looks good.
8-8: Registry URI pattern looks solid.The shift from
registryCommittoregistryUriwith an optional empty default aligns well with the new configuration approach. This allows for flexible registry pinning.typescript/warp-monitor/src/types.ts (2)
1-2: Good use of type-only imports.Using
import typeforChainNameandAddressis the right approach here since these are used purely at the type level, which can help with tree-shaking and build optimization.
24-29: WarpMonitorConfig interface looks well-designed.The configuration interface covers all the essential service parameters mentioned in the PR objectives. The optional fields (
coingeckoApiKeyandregistryUri) provide good flexibility for different deployment scenarios.typescript/infra/src/warp/helm.ts (1)
59-62: Registry URI construction looks proper.Building the registry URI with the
/tree/{commit}format usingDEFAULT_GITHUB_REGISTRYprovides a clean way to reference specific registry versions.typescript/warp-monitor/src/utils.test.ts (1)
1-41: Utility tests cover the essentials.The test coverage for logger and error handling utilities looks appropriate. The
tryFnerror test (lines 32-39) is particularly important since it validates that errors are caught and logged rather than propagated, which is the intended behavior.typescript/warp-monitor/Dockerfile (2)
1-79: Dockerfile structure looks solid.The multi-stage build with selective package copying and final bundle-only image is well done. The progression from node:20-slim (builder) to node:20-alpine (runner) gives you a good balance between build capabilities and final image size.
The 28x size reduction mentioned in the PR is impressive and this Dockerfile structure is a big part of that.
9-12: Remove Foundry installation from warp-monitor Dockerfile.warp-monitor is a pure TypeScript service that doesn't compile Solidity. The build scripts only use
tscfor TypeScript andnccfor bundling—no forge or soldeer references anywhere in the package or its dependencies. Foundry adds unnecessary bloat to the image and should be removed to speed up builds.typescript/warp-monitor/src/metrics.test.ts (5)
19-20: Good documentation about registry behavior.The note explaining why the registry isn't cleared between tests is helpful context. Since gauges are registered at module load time, this prevents potential issues with re-registration.
34-47: Clean mock helper functions.The
createMockWarpCoreandcreateMockTokenhelpers keep the tests readable and avoid repetition. Nice approach.
132-159: Excellent test for related chains logic.This test validates that the current chain is properly excluded from
related_chain_namesand that the remaining chains are sorted. This kind of specific label validation helps catch subtle metric bugs that could affect monitoring dashboards.
161-184: Good coverage of xERC20 labeling.Verifying that xERC20 tokens get the correct
token_standard="xERC20"label (rather than the internalEvmHypXERC20enum name) is important for consistent metric naming. This ensures the Prometheus metrics match what Grafana dashboards expect.
1-304: Comprehensive metrics test coverage.The test suite thoroughly validates all the metric update functions with good coverage of edge cases (zero limits, small balances, multi-chain scenarios). The tests serve as both validation and documentation for how metrics should be labeled and structured.
This will help ensure Prometheus metrics remain compatible with existing Grafana dashboards as noted in the PR objectives.
typescript/infra/helm/warp-routes/templates/_helpers.tpl (1)
73-84: Environment variable configuration looks proper, ogre-all.The new env-based configuration is clean and straightforward. The conditional
REGISTRY_URIand the secret reference forCOINGECKO_API_KEYusing$(COINGECKO_API_KEY)syntax are correctly set up for Kubernetes. HardcodingCHECK_FREQUENCYto"30000"matches the default in the service code.One small thing to ponder - if you ever need to tune
CHECK_FREQUENCYorLOG_LEVELper deployment, you might want to parameterize these via.Valuestoo. But for now, this keeps things simple in your swamp.typescript/warp-monitor/src/service.ts (1)
31-42: Version reading is solid, but watch out for bundled deployments.When
nccbundles everything into a single file, the relative path topackage.jsonmight not resolve correctly since../package.jsonassumes the original directory structure. The catch block handles this gracefully by returning'unknown', so it won't break anything - just something to be aware of if version tracking matters to ye.typescript/warp-monitor/src/index.ts (1)
1-22: Clean barrel exports, like organizing the swamp nice and tidy.The public API surface is well-defined with clear separation between the main class, metrics utilities, types, and logger helpers. Using
.jsextensions for ESM imports is correct.typescript/warp-monitor/package.json (2)
1-67: Package structure is solid overall.The package manifest is well-organized with proper ESM configuration, bin entry point, sensible scripts (including the ncc bundling workflow), and appropriate engine constraints. The metadata and repository info are all in order.
31-31: No changes needed here – this is the right way to do it.The
@hyperlane-xyz/registrydependency usescatalog:protocol, which is exactly how this monorepo manages external npm packages. The pnpm catalog inpnpm-workspace.yamlpins it to version23.7.0, andcatalogMode: strictensures all packages follow this pattern. It's centralized version management, which is cleaner than scattering version numbers across individual package.json files.typescript/warp-monitor/src/utils.ts (2)
28-37: ThetryFnhelper does its job, but swallows all errors.This is fine for the monitoring use case where you don't want one failing token check to bring down the whole service. Just be mindful that errors are only logged, never propagated - if callers ever need to know whether something succeeded, they'd need a different pattern.
7-18: Logger initialization is thoughtful.Setting both the module-scoped logger and the root logger ensures consistent logging throughout the application. The dynamic import for
createServiceLoggeris an interesting choice - probably to handle some module loading nuances..github/workflows/warp-monitor-docker.yml (2)
115-124: Change detection looks good, but the git diff might get finicky.The
git diff --name-only origin/${{ github.base_ref }}...HEADcommand assumesorigin/${{ github.base_ref }}is available. Since you're usingfetch-depth: 0, this should work, but if the base branch hasn't been fetched (edge case), it could fail silently. Thegrep -qEwill return false, so it won't break the workflow - it'll just not comment.Might be worth adding a fetch of the base branch explicitly if you run into issues.
1-51: Workflow setup is proper, like a well-organized swamp.The trigger paths include all the dependencies (sdk, provider-sdk, utils) that could affect the warp-monitor build, which is smart. Concurrency handling will prevent resource waste on rapid pushes. The secret check pattern is a good defensive practice.
typescript/warp-monitor/src/metrics.ts (1)
122-193: Metric update functions are well-organized.The labeling strategy is consistent, and the value-at-risk calculation across all chains is a nice touch. Logging at each update helps with debugging without being excessive.
typescript/warp-monitor/src/monitor.ts (6)
50-57: WarpMonitor class setup is clean and simple.The constructor just stores config and registry - no heavy initialization. This follows good practices by deferring expensive operations to
start().
73-96: Registry and WarpCore initialization is solid.The sequence of fetching metadata, addresses, building the provider, and creating WarpCore is logically organized. The null check for warp route config (lines 88-92) properly throws if the route doesn't exist.
One thing to keep in mind - if the registry is temporarily unavailable during startup, this will throw and exit. That's probably the right behavior for a daemon that needs valid config to function.
139-155: Polling loop is robust, like an ogre's endurance.The
while(true)withtryFnwrapper ensures the monitor keeps running even if individual updates fail. Running all token updates in parallel withPromise.allis efficient. The sleep between iterations prevents hammering the RPC endpoints.
215-239: Early return and type validation are well-handled.The check for missing
warpDeployConfigand the subsequent type validation for xERC20 tokens are good defensive programming. Logging errors with context (token symbol, chain, expected vs actual type) will help debugging.One minor observation - the early
returnat line 220 exits beforeawait Promise.all(promises)at line 292, so any promises already pushed (bridged balance, ATA payer) won't be awaited. This is probably fine since those operations are wrapped intryFnand will complete eventually, but worth being aware of.
600-607: CoinGecko price fetching could use a bit more defensive handling.When
getTokenPriceByIdsreturns an array, you're takingprices[0]. If the array is empty (e.g., unknown coin ID), this will returnundefined, which is handled. But if the API returnsnullinside the array (e.g.,[null]), you'd getnullinstead ofundefined.Not a big deal since the callers check for truthiness anyway, but something to be aware of.
486-489: TODO noted for adapter usage.The comment about using an adapter instead of the factory is a good self-reminder. The current implementation works fine, but refactoring to use a proper adapter would improve consistency with the rest of the codebase.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
typescript/warp-monitor/src/metrics.ts (1)
240-256: Missing requiredtoken_addresslabel, mate.When you look back at how
walletBalanceGaugeis created (lines 85-104), it expects these labels:chain,wallet_address,wallet_name,token_address,token_symbol,token_name. But here you're only providing five of them—token_addressis missing. The prom-client library will throw a right fit when the label set doesn't match, and your metrics won't get recorded.For native balances, you can set
token_addressto an empty string or a sentinel value like'0x0'.🔎 Suggested fix
export function updateNativeWalletBalanceMetrics( balance: NativeWalletBalance, ): void { const logger = getLogger(); walletBalanceGauge .labels({ chain: balance.chain, wallet_address: balance.walletAddress, wallet_name: balance.walletName, + token_address: '0x0', token_symbol: 'Native', token_name: 'Native', }) .set(balance.balance); logger.info('Native wallet balance updated', { balanceInfo: balance, }); }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
typescript/infra/src/warp/helm.tstypescript/warp-monitor/src/metrics.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- typescript/infra/src/warp/helm.ts
🧰 Additional context used
📓 Path-based instructions (1)
typescript/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
typescript/**/*.{ts,tsx}: UseChainMapfor per-chain configurations in TypeScript
Import types from@hyperlane-xyz/sdkwhen using TypeScript SDK types
Files:
typescript/warp-monitor/src/metrics.ts
🧠 Learnings (2)
📚 Learning: 2025-09-05T15:13:08.394Z
Learnt from: ltyu
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6992
File: typescript/sdk/src/token/types.test.ts:188-197
Timestamp: 2025-09-05T15:13:08.394Z
Learning: WarpRouteDeployConfigSchema.safeParse automatically populates missing token fields during preprocessing, so manual specification of top-level token fields in RoutingFee test cases is not necessary.
Applied to files:
typescript/warp-monitor/src/metrics.ts
📚 Learning: 2025-09-18T15:49:20.478Z
Learnt from: yorhodes
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6750
File: solidity/contracts/token/bridge/EverclearTokenBridge.sol:212-212
Timestamp: 2025-09-18T15:49:20.478Z
Learning: EverclearTokenBridge sends funds directly to recipients for ERC20 transfers, while EverclearEthBridge sends funds to remote routers that handle WETH unwrapping and ETH delivery. The virtual _getReceiver and _getIntentCalldata functions enable this architectural difference between the two bridge implementations.
Applied to files:
typescript/warp-monitor/src/metrics.ts
🧬 Code graph analysis (1)
typescript/warp-monitor/src/metrics.ts (3)
typescript/sdk/src/index.ts (1)
TokenStandard(732-732)typescript/warp-monitor/src/utils.ts (1)
getLogger(20-22)typescript/warp-monitor/src/types.ts (1)
NativeWalletBalance(17-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (60)
- GitHub Check: cli-evm-e2e-matrix (core-apply)
- GitHub Check: cli-evm-e2e-matrix (warp-send)
- GitHub Check: cli-evm-e2e-matrix (warp-init)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-4)
- GitHub Check: cli-evm-e2e-matrix (warp-read)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
- GitHub Check: cli-evm-e2e-matrix (core-check)
- GitHub Check: cli-evm-e2e-matrix (warp-check-2)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-3)
- GitHub Check: cli-evm-e2e-matrix (warp-check-1)
- GitHub Check: cli-evm-e2e-matrix (status)
- GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-5)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
- GitHub Check: cli-evm-e2e-matrix (core-init)
- GitHub Check: cli-evm-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
- GitHub Check: cli-evm-e2e-matrix (core-read)
- GitHub Check: cli-evm-e2e-matrix (relay)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
- GitHub Check: env-test-matrix (mainnet3, ethereum, core)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
- GitHub Check: env-test-matrix (testnet4, sepolia, core)
- GitHub Check: cli-cosmos-e2e-matrix (core-apply)
- GitHub Check: env-test-matrix (mainnet3, optimism, igp)
- GitHub Check: cli-radix-e2e-matrix (warp-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
- GitHub Check: env-test-matrix (mainnet3, optimism, core)
- GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
- GitHub Check: cli-radix-e2e-matrix (core-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-read)
- GitHub Check: cli-cosmos-e2e-matrix (warp-read)
- GitHub Check: cli-cosmos-e2e-matrix (core-check)
- GitHub Check: aleo-sdk-e2e-run
- GitHub Check: cli-radix-e2e-matrix (core-apply)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: pnpm-test-run
- GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
- GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
- GitHub Check: cosmos-sdk-e2e-run
- GitHub Check: cli-install-test-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
- GitHub Check: infra-test
- GitHub Check: build-and-push-to-gcr
- GitHub Check: build-and-push-to-gcr
- GitHub Check: e2e-matrix (evm)
- GitHub Check: lint-rs
- GitHub Check: test-rs
- GitHub Check: lander-coverage
🔇 Additional comments (7)
typescript/warp-monitor/src/metrics.ts (7)
1-17: Imports look solid.Type-only imports from SDK and utils are used properly, and the new http and getLogger imports make sense for the server functionality.
21-21: Type rename follows conventions.Capitalizing to
SupportedTokenStandardsaligns with TypeScript naming conventions for type aliases.Also applies to: 32-32, 64-64
85-106: Helper function nicely consolidates gauge creation.The
createWalletBalanceGaugehelper makes it easy to create wallet balance gauges with consistent labels and optional extensions.
122-193: Logger initialization pattern looks good.Initializing the logger at the start of the function and using it for structured logging throughout is clean and consistent.
195-238: Lockbox balance metrics update is consistent.The same logger pattern and structured logging approach is applied here, which is good for maintainability.
258-290: xERC20 limits update is well-structured.The iteration over limit types and structured logging make this easy to follow and debug.
292-324: Past issues have been sorted out.The previous review flagged the missing hyphen in
Content-Typeand the hanging client when metrics collection failed. Both of those are fixed now—line 314 has the correct header format, and lines 316-321 properly handle errors by logging and sending a 500 response. The server implementation looks solid.
Use pinned Foundry binaries from solidity/.foundryrc instead of curl|bash installer for reproducibility. Uses bash shell for pipefail support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Always build on pushes to main (match monorepo behavior) - Only trigger PR builds for direct warp-monitor changes - Remove unnecessary check-changes step 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/warp-monitor-docker.ymltypescript/warp-monitor/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/warp-monitor-docker.yml
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/mainnet_config.json in future code reviews as requested by paulbalaji.
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/testnet_config.json in future code reviews as requested by paulbalaji.
📚 Learning: 2025-12-22T16:50:19.890Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7565
File: typescript/ccip-server/Dockerfile:10-11
Timestamp: 2025-12-22T16:50:19.890Z
Learning: Standardize Foundry installation in Dockerfiles by using the official curl -L https://foundry.paradigm.xyz | bash followed by foundryup. This pattern is already used across multiple Dockerfiles in the repo and should be retained for consistency and reliability wherever Foundry is installed.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-08-13T16:53:55.163Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6891
File: typescript/infra/config/environments/mainnet3/funding.ts:22-22
Timestamp: 2025-08-13T16:53:55.163Z
Learning: In Hyperlane mainnet3 configs, funding.ts uses 'gcr.io/abacus-labs-dev/hyperlane-monorepo' docker image while agent.ts uses 'gcr.io/abacus-labs-dev/hyperlane-agent' docker image. These are different images with independent tag cycles, so tag consistency across them is not expected.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-11-25T17:10:33.369Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: solidity/foundry.toml:8-8
Timestamp: 2025-11-25T17:10:33.369Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, when using pnpm (instead of Yarn), Foundry's `allow_paths` in solidity/foundry.toml should be set to `["./node_modules"]` rather than `["../node_modules"]` because pnpm's default node_modules structure places dependencies locally in the workspace subdirectory, not requiring access to the parent directory's node_modules.
Applied to files:
typescript/warp-monitor/Dockerfile
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (63)
- GitHub Check: cli-evm-e2e-matrix (warp-read)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-4)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
- GitHub Check: cli-evm-e2e-matrix (warp-check-5)
- GitHub Check: cli-evm-e2e-matrix (warp-init)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
- GitHub Check: cli-evm-e2e-matrix (status)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-3)
- GitHub Check: cli-evm-e2e-matrix (warp-check-1)
- GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
- GitHub Check: cli-evm-e2e-matrix (warp-send)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
- GitHub Check: cli-evm-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
- GitHub Check: cli-evm-e2e-matrix (core-read)
- GitHub Check: cli-evm-e2e-matrix (warp-check-2)
- GitHub Check: cli-evm-e2e-matrix (core-init)
- GitHub Check: cli-evm-e2e-matrix (core-apply)
- GitHub Check: cli-evm-e2e-matrix (core-check)
- GitHub Check: cli-evm-e2e-matrix (relay)
- GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
- GitHub Check: env-test-matrix (mainnet3, ethereum, core)
- GitHub Check: env-test-matrix (mainnet3, optimism, igp)
- GitHub Check: env-test-matrix (testnet4, sepolia, core)
- GitHub Check: env-test-matrix (mainnet3, optimism, core)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
- GitHub Check: cli-cosmos-e2e-matrix (core-read)
- GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-check)
- GitHub Check: cli-cosmos-e2e-matrix (warp-read)
- GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: pnpm-test-run
- GitHub Check: cli-radix-e2e-matrix (core-apply)
- GitHub Check: cli-cosmos-e2e-matrix (core-apply)
- GitHub Check: cli-radix-e2e-matrix (core-deploy)
- GitHub Check: cli-radix-e2e-matrix (warp-deploy)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
- GitHub Check: aleo-sdk-e2e-run
- GitHub Check: cosmos-sdk-e2e-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
- GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
- GitHub Check: cli-install-test-run
- GitHub Check: infra-test
- GitHub Check: e2e-matrix (evm)
- GitHub Check: agent-configs (mainnet3)
- GitHub Check: agent-configs (testnet4)
- GitHub Check: lint-prettier
- GitHub Check: test-rs
- GitHub Check: lint-rs
- GitHub Check: lander-coverage
- GitHub Check: build-and-push-to-gcr
- GitHub Check: build-and-push-to-gcr
🔇 Additional comments (4)
typescript/warp-monitor/Dockerfile (4)
1-7: Base image and dependencies look solid.The slim image with build essentials and cleanup is a sensible approach. No concerns here.
18-43: Dependency installation is well-structured.The layer caching strategy (package.json first, then frozen lockfile install) and the selective copying for workspace dependencies are spot on. Keeps the build efficient.
45-62: Build and bundle step looks good.Copying source after deps keeps your layers cached properly, and the turbo filter ensures you're only bundling what's needed. Clean approach.
9-16: Foundry installation approach is solid.This setup is exactly right—the
FOUNDRY_VERSIONargument gets fed from the centralizedsolidity/.foundryrcfile in CI (which containsv1.5.0), so there's no risk of a missing value. The deliberate move to pinned binaries rather than the installer script keeps your image reproducible and consistent across builds. Architecture detection for arm64/amd64 looks good too. All layers fit together like layers in an ogre, mate.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
typescript/warp-monitor/src/metrics.ts (1)
293-325: Metrics server looks tidy after the fixes.The error handling now properly sends a 500 response instead of leavin' the client hangin' like a lost donkey. Header name is correct too.
One small thing though - if someone sets
PROMETHEUS_PORTto somethin' that ain't a number,parseIntwill give youNaNand that could cause unexpected behavior whenlistenis called.🔎 Optional: Add port validation
- .listen(parseInt(process.env['PROMETHEUS_PORT'] || '9090')); + .listen((() => { + const port = parseInt(process.env['PROMETHEUS_PORT'] || '9090', 10); + if (isNaN(port) || port < 0 || port > 65535) { + throw new Error(`Invalid PROMETHEUS_PORT: ${process.env['PROMETHEUS_PORT']}`); + } + return port; + })());typescript/warp-monitor/src/monitor.ts (3)
139-155: Infinite polling loop could use a shutdown mechanism.The
while (true)loop does the job, but there's no way to gracefully stop it. If this ever needs to be shut down cleanly (for testing, pod termination signals, etc.), you'd have no handle to do so.🔎 Consider adding a shutdown mechanism
export class WarpMonitor { private readonly config: WarpMonitorConfig; private readonly registry: IRegistry; + private isRunning = false; constructor(config: WarpMonitorConfig, registry: IRegistry) { this.config = config; this.registry = registry; } + stop(): void { + this.isRunning = false; + } // In pollAndUpdateWarpRouteMetrics: - while (true) { + this.isRunning = true; + while (this.isRunning) {
486-489: TODO about using adapter.There's a TODO here about using an adapter instead of directly connecting with the factory. Worth tracking if this is intended to be addressed.
Would you like me to open an issue to track refactoring this to use an adapter instead of direct factory connection?
600-607: Price getter could silently return undefined for valid IDs.If
getTokenPriceByIdsreturns an array but it's empty (e.g., the coingeckoId wasn't found in CoinGecko's database),prices[0]will beundefined. This is technically fine since the return type accounts for it, but there's no logging to help debug why a price wasn't found.🔎 Optional: Add debug logging for price lookup failures
private async getCoingeckoPrice( tokenPriceGetter: CoinGeckoTokenPriceGetter, coingeckoId: string, ): Promise<number | undefined> { + const logger = getLogger(); const prices = await tokenPriceGetter.getTokenPriceByIds([coingeckoId]); - if (!prices) return undefined; + if (!prices || prices.length === 0 || prices[0] === undefined) { + logger.debug({ coingeckoId }, 'No price returned from CoinGecko'); + return undefined; + } return prices[0]; }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
typescript/warp-monitor/src/metrics.tstypescript/warp-monitor/src/monitor.ts
🧰 Additional context used
📓 Path-based instructions (1)
typescript/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
typescript/**/*.{ts,tsx}: UseChainMapfor per-chain configurations in TypeScript
Import types from@hyperlane-xyz/sdkwhen using TypeScript SDK types
Files:
typescript/warp-monitor/src/metrics.tstypescript/warp-monitor/src/monitor.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/mainnet_config.json in future code reviews as requested by paulbalaji.
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/testnet_config.json in future code reviews as requested by paulbalaji.
📚 Learning: 2025-09-05T15:13:08.394Z
Learnt from: ltyu
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6992
File: typescript/sdk/src/token/types.test.ts:188-197
Timestamp: 2025-09-05T15:13:08.394Z
Learning: WarpRouteDeployConfigSchema.safeParse automatically populates missing token fields during preprocessing, so manual specification of top-level token fields in RoutingFee test cases is not necessary.
Applied to files:
typescript/warp-monitor/src/metrics.ts
📚 Learning: 2025-09-18T15:49:20.478Z
Learnt from: yorhodes
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6750
File: solidity/contracts/token/bridge/EverclearTokenBridge.sol:212-212
Timestamp: 2025-09-18T15:49:20.478Z
Learning: EverclearTokenBridge sends funds directly to recipients for ERC20 transfers, while EverclearEthBridge sends funds to remote routers that handle WETH unwrapping and ETH delivery. The virtual _getReceiver and _getIntentCalldata functions enable this architectural difference between the two bridge implementations.
Applied to files:
typescript/warp-monitor/src/metrics.ts
🧬 Code graph analysis (1)
typescript/warp-monitor/src/metrics.ts (2)
typescript/warp-monitor/src/utils.ts (1)
getLogger(20-22)typescript/warp-monitor/src/types.ts (1)
NativeWalletBalance(17-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (61)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
- GitHub Check: cli-evm-e2e-matrix (warp-check-3)
- GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
- GitHub Check: cli-evm-e2e-matrix (warp-send)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-init)
- GitHub Check: cli-evm-e2e-matrix (warp-check-5)
- GitHub Check: cli-evm-e2e-matrix (warp-check-4)
- GitHub Check: cli-evm-e2e-matrix (warp-check-2)
- GitHub Check: cli-evm-e2e-matrix (warp-read)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
- GitHub Check: cli-evm-e2e-matrix (warp-check-1)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-evm-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
- GitHub Check: cli-evm-e2e-matrix (status)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
- GitHub Check: cli-evm-e2e-matrix (core-check)
- GitHub Check: cli-evm-e2e-matrix (core-apply)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
- GitHub Check: cli-evm-e2e-matrix (core-init)
- GitHub Check: cli-evm-e2e-matrix (relay)
- GitHub Check: cli-evm-e2e-matrix (core-read)
- GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
- GitHub Check: env-test-matrix (mainnet3, ethereum, core)
- GitHub Check: cli-cosmos-e2e-matrix (warp-read)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
- GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
- GitHub Check: env-test-matrix (mainnet3, optimism, igp)
- GitHub Check: env-test-matrix (testnet4, sepolia, core)
- GitHub Check: cli-cosmos-e2e-matrix (core-check)
- GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-apply)
- GitHub Check: cli-cosmos-e2e-matrix (core-read)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
- GitHub Check: aleo-sdk-e2e-run
- GitHub Check: env-test-matrix (mainnet3, optimism, core)
- GitHub Check: cli-radix-e2e-matrix (warp-deploy)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-radix-e2e-matrix (core-deploy)
- GitHub Check: cli-radix-e2e-matrix (core-apply)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
- GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
- GitHub Check: pnpm-test-run
- GitHub Check: cli-install-test-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
- GitHub Check: cosmos-sdk-e2e-run
- GitHub Check: build-and-push-to-gcr
- GitHub Check: build-and-push-to-gcr
- GitHub Check: infra-test
- GitHub Check: e2e-matrix (evm)
- GitHub Check: lint-prettier
- GitHub Check: test-rs
- GitHub Check: lint-rs
- GitHub Check: lander-coverage
🔇 Additional comments (7)
typescript/warp-monitor/src/metrics.ts (3)
1-17: Imports look good, mate.Type-only imports for SDK types and the new
getLoggerutility are properly organized. Usingtypekeyword for imports that are only used as types is a nice touch for the swamp.
85-106: Solid helper for gauge creation.The
createWalletBalanceGaugefactory is a tidy way to avoid duplicatin' yourself. Extendable with additional labels and properly registered. Nothin' onion-y about this one.
122-193: Token balance metric updates look proper.The logger integration and structured logging with labels give good observability into what's happenin' in the swamp. The value-at-risk calculation for all chains is a nice touch.
typescript/warp-monitor/src/monitor.ts (4)
1-43: Imports are well organized.Good use of type imports where appropriate. The mix of ethers, hyperlane core/registry/sdk/utils, and local modules is cleanly structured. Like layers of an onion, each has its purpose.
50-116: WarpMonitor class initialization looks solid.The constructor is simple and the
start()method properly sets up logger bindings, starts the metrics server, builds theMultiProtocolProviderwith mailboxes merged, and validates the warp route config exists before proceeding. Good structured logging throughout.
295-345: Token bridged balance retrieval is well structured.Good defensive checks for non-Hyperlane tokens and undefined bridged supply. The price lookup is correctly scoped to collateralized and lockbox tokens. Logging warnings for edge cases is helpful for debugging.
466-469: Minimal ABI defined inline - acceptable but could be shared.This works fine for now. If other parts of the codebase need the same ABI, you might want to move it somewhere shared. But for a single use case in this monitor, keepin' it local ain't a problem.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
typescript/warp-monitor/src/monitor.ts (2)
139-153: Consider the impact of parallel token updates on RPC endpoints.Right now you're updating all tokens in parallel (line 141) with
Promise.all. For deployments with many tokens across chains, this could overwhelm rate-limited RPC endpoints—especially public ones. Based on learnings from similar code, parallel requests can cause rate limiting issues.If you start seeing RPC errors in production, you might want to process tokens sequentially or in smaller batches, even though it'll be slower.
Based on learnings from past RPC optimization reviews.
473-509: TODO comment indicates planned refactor.There's a TODO at line 491 to use an adapter instead of directly connecting with the factory. The current implementation works, but using an adapter would be more consistent with the rest of the codebase.
Would you like me to open an issue to track this refactor?
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
typescript/warp-monitor/src/monitor.ts
🧰 Additional context used
📓 Path-based instructions (1)
typescript/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
typescript/**/*.{ts,tsx}: UseChainMapfor per-chain configurations in TypeScript
Import types from@hyperlane-xyz/sdkwhen using TypeScript SDK types
Files:
typescript/warp-monitor/src/monitor.ts
🧠 Learnings (1)
📚 Learning: 2025-07-22T22:21:54.918Z
Learnt from: xeno097
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6746
File: typescript/sdk/src/timelock/evm/EvmTimelockReader.ts:155-166
Timestamp: 2025-07-22T22:21:54.918Z
Learning: When reviewing RPC call optimizations in timelock-related code, be mindful that parallel requests using Promise.all can cause rate limiting issues with public RPC endpoints. Sequential processing, while slower, is often preferred for reliability and to avoid overwhelming RPC providers.
Applied to files:
typescript/warp-monitor/src/monitor.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (42)
- GitHub Check: cli-evm-e2e-matrix (warp-check-5)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
- GitHub Check: cli-evm-e2e-matrix (warp-send)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
- GitHub Check: cli-evm-e2e-matrix (warp-read)
- GitHub Check: cli-evm-e2e-matrix (warp-check-1)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
- GitHub Check: cli-evm-e2e-matrix (warp-check-3)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
- GitHub Check: cli-evm-e2e-matrix (warp-check-4)
- GitHub Check: cli-evm-e2e-matrix (warp-check-2)
- GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-evm-e2e-matrix (relay)
- GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (core-apply)
- GitHub Check: env-test-matrix (mainnet3, ethereum, core)
- GitHub Check: cli-radix-e2e-matrix (core-deploy)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
- GitHub Check: env-test-matrix (mainnet3, optimism, core)
- GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (warp-read)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
- GitHub Check: cli-radix-e2e-matrix (core-apply)
- GitHub Check: cli-radix-e2e-matrix (warp-deploy)
- GitHub Check: cosmos-sdk-e2e-run
- GitHub Check: aleo-sdk-e2e-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
- GitHub Check: e2e-matrix (evm)
- GitHub Check: lint-rs
- GitHub Check: lander-coverage
- GitHub Check: test-rs
- GitHub Check: build-and-push-to-gcr
🔇 Additional comments (16)
typescript/warp-monitor/src/monitor.ts (16)
1-43: Imports look solid.The type imports from
@hyperlane-xyz/sdkare properly used, and the structure follows the coding guidelines. Good use of type-only imports where appropriate.
45-48: Interface definition is clean.The
XERC20Infointerface is well-defined for internal use.
50-57: Constructor is straightforward.Clean initialization with readonly fields for config and registry.
59-116: Initialization logic is well-structured.The method properly orchestrates registry access, provider setup, and config validation before starting the monitoring loop.
157-295: Token metrics update flow handles all cases properly.The method correctly handles different token types (Sealevel, xERC20, extra lockboxes) and properly awaits all promises before returning, even on early exits. The previous concern about unawaited promises has been addressed.
297-347: Balance retrieval logic is sound.The method properly handles different token types and gracefully returns
undefinedwhen balance can't be determined. Optional price handling is appropriate.
349-375: Collateral info retrieval is implemented correctly.Method properly chains contract calls to extract token metadata from the lockbox.
377-379: Helper method does its job.Simple wrapper around token formatting.
385-413: Sealevel ATA payer balance logic is correct.The method properly validates protocol type and retrieves the native balance for the ATA payer account.
415-447: xERC20 info retrieval handles all standard variants.The method correctly handles both xERC20 and xERC20Lockbox token standards with proper adapter casting.
449-466: Limit retrieval efficiently fetches all values.Good use of
Promise.allto parallelize the four limit queries and proper formatting of results.
468-471: Minimal ABI is properly defined.The readonly constant with const assertion is the right approach for this minimal contract interface.
511-523: Contract instantiation is straightforward.Helper method correctly creates a Contract instance with the minimal ABI for lockbox interactions.
525-577: Extra lockbox balance retrieval has proper error handling.The method correctly handles the case where a token isn't xERC20 and includes a try/catch block for balance fetching with appropriate error logging. The explicit
undefinedreturn pattern was already noted in a previous review.
579-600: Price lookup gracefully handles missing CoinGecko IDs.The method appropriately returns
undefinedwhen a token doesn't have a CoinGecko ID, which is expected for certain token types.
602-609: CoinGecko price lookup is simple and correct.The method properly handles the case when prices aren't available. The rate limiting concern for CoinGecko is already addressed earlier in the code with appropriate warnings when no API key is provided.
antigremlin
left a comment
There was a problem hiding this comment.
Cool. Same suggestions on initialising the VERSION to be printed to the logs, and making the package private.
ncc cannot bundle dynamically imported packages. Mark the GCP logging config as external and install it separately in the Docker image. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add missing @hyperlane-xyz/eslint-config devDependency - Exclude warp-monitor from main Dockerfile check (has its own Dockerfile) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
typescript/warp-monitor/Dockerfile (1)
76-76: Using npm instead of pnpm in the runner stage.You're installing
@google-cloud/pino-logging-gcp-configwith npm here, but the builder used pnpm. This works fine since it's a standalone install with no lockfile, but mixing package managers could lead to version drift if the catalog definition in the builder resolves to a different version than npm's latest.For consistency and reproducibility, consider extracting the resolved version from the builder's lockfile and pinning it explicitly.
🔎 Alternative approach for pinned version
Extract the version during build and pin it:
+# Extract the resolved version of the GCP logging package from the builder +RUN --mount=from=builder,source=/hyperlane-monorepo/pnpm-lock.yaml,target=/tmp/pnpm-lock.yaml \ + VERSION=$(grep -A 2 "@google-cloud/pino-logging-gcp-config" /tmp/pnpm-lock.yaml | grep "version:" | head -1 | awk '{print $2}') && \ + npm install "@google-cloud/pino-logging-gcp-config@${VERSION}" -RUN npm install @google-cloud/pino-logging-gcp-configOr simpler—just pin a specific version directly:
-RUN npm install @google-cloud/pino-logging-gcp-config +RUN npm install @google-cloud/pino-logging-gcp-config@^6.0.0
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
scripts/check-package-json.shtypescript/warp-monitor/Dockerfiletypescript/warp-monitor/package.json
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7545
File: typescript/infra/src/rebalancer/helm.ts:82-83
Timestamp: 2025-12-29T19:45:05.429Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, Docker image tags in Helm managers (e.g., typescript/infra/src/rebalancer/helm.ts) are intentionally hardcoded for reproducibility and explicit version control, rather than using dynamically generated CI tags.
📚 Learning: 2025-08-26T13:45:29.848Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: typescript/infra/config/environments/testnet4/ism/verification.json:3835-3939
Timestamp: 2025-08-26T13:45:29.848Z
Learning: Skip reviewing verification.json files in typescript/infra/config/environments/testnet4/ism/verification.json and similar verification.json files as requested by paulbalaji.
Applied to files:
scripts/check-package-json.sh
📚 Learning: 2025-12-29T19:45:05.429Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7545
File: typescript/infra/src/rebalancer/helm.ts:82-83
Timestamp: 2025-12-29T19:45:05.429Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, Docker image tags in Helm managers (e.g., typescript/infra/src/rebalancer/helm.ts) are intentionally hardcoded for reproducibility and explicit version control, rather than using dynamically generated CI tags.
Applied to files:
typescript/warp-monitor/Dockerfiletypescript/warp-monitor/package.json
📚 Learning: 2025-08-26T13:46:37.695Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/mainnet_config.json in future code reviews as requested by paulbalaji.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-08-26T13:46:37.695Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/mainnet_config.json:965-965
Timestamp: 2025-08-26T13:46:37.695Z
Learning: In the repository hyperlane-xyz/hyperlane-monorepo, skip reviewing the file rust/main/config/testnet_config.json in future code reviews as requested by paulbalaji.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-12-22T16:50:19.890Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7565
File: typescript/ccip-server/Dockerfile:10-11
Timestamp: 2025-12-22T16:50:19.890Z
Learning: Standardize Foundry installation in Dockerfiles by using the official curl -L https://foundry.paradigm.xyz | bash followed by foundryup. This pattern is already used across multiple Dockerfiles in the repo and should be retained for consistency and reliability wherever Foundry is installed.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-08-13T16:53:55.163Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6891
File: typescript/infra/config/environments/mainnet3/funding.ts:22-22
Timestamp: 2025-08-13T16:53:55.163Z
Learning: In Hyperlane mainnet3 configs, funding.ts uses 'gcr.io/abacus-labs-dev/hyperlane-monorepo' docker image while agent.ts uses 'gcr.io/abacus-labs-dev/hyperlane-agent' docker image. These are different images with independent tag cycles, so tag consistency across them is not expected.
Applied to files:
typescript/warp-monitor/Dockerfile
📚 Learning: 2025-11-25T17:10:33.369Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: solidity/foundry.toml:8-8
Timestamp: 2025-11-25T17:10:33.369Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, when using pnpm (instead of Yarn), Foundry's `allow_paths` in solidity/foundry.toml should be set to `["./node_modules"]` rather than `["../node_modules"]` because pnpm's default node_modules structure places dependencies locally in the workspace subdirectory, not requiring access to the parent directory's node_modules.
Applied to files:
typescript/warp-monitor/Dockerfiletypescript/warp-monitor/package.json
📚 Learning: 2025-11-26T13:28:51.658Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: typescript/cli/package.json:20-20
Timestamp: 2025-11-26T13:28:51.658Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, hyperlane-xyz/registry is maintained in a separate repository and published to npm, so it should use a pinned version (e.g., "23.6.0") rather than the workspace protocol ("workspace:*") that other internal Hyperlane packages use.
Applied to files:
typescript/warp-monitor/package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (61)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
- GitHub Check: cli-evm-e2e-matrix (warp-send)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
- GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
- GitHub Check: cli-evm-e2e-matrix (core-init)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
- GitHub Check: cli-evm-e2e-matrix (core-read)
- GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
- GitHub Check: cli-evm-e2e-matrix (relay)
- GitHub Check: cli-evm-e2e-matrix (warp-read)
- GitHub Check: cli-evm-e2e-matrix (warp-check-4)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
- GitHub Check: cli-evm-e2e-matrix (warp-check-2)
- GitHub Check: cli-evm-e2e-matrix (core-apply)
- GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
- GitHub Check: cli-evm-e2e-matrix (warp-init)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-1)
- GitHub Check: cli-evm-e2e-matrix (warp-check-5)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
- GitHub Check: cli-evm-e2e-matrix (warp-check-3)
- GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
- GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
- GitHub Check: cli-evm-e2e-matrix (core-deploy)
- GitHub Check: cli-evm-e2e-matrix (core-check)
- GitHub Check: cli-evm-e2e-matrix (status)
- GitHub Check: env-test-matrix (testnet4, sepolia, core)
- GitHub Check: env-test-matrix (mainnet3, optimism, core)
- GitHub Check: env-test-matrix (mainnet3, ethereum, core)
- GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
- GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
- GitHub Check: env-test-matrix (mainnet3, optimism, igp)
- GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-check)
- GitHub Check: cli-radix-e2e-matrix (core-apply)
- GitHub Check: cli-cosmos-e2e-matrix (core-read)
- GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
- GitHub Check: cli-cosmos-e2e-matrix (core-apply)
- GitHub Check: aleo-sdk-e2e-run
- GitHub Check: cli-cosmos-e2e-matrix (warp-read)
- GitHub Check: cli-radix-e2e-matrix (warp-deploy)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
- GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
- GitHub Check: cli-radix-e2e-matrix (core-deploy)
- GitHub Check: cli-install-test-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
- GitHub Check: pnpm-test-run
- GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
- GitHub Check: cosmos-sdk-e2e-run
- GitHub Check: infra-test
- GitHub Check: build-and-push-to-gcr
- GitHub Check: build-and-push-to-gcr
- GitHub Check: e2e-matrix (evm)
- GitHub Check: agent-configs (mainnet3)
- GitHub Check: lint-rs
- GitHub Check: test-rs
- GitHub Check: lander-coverage
🔇 Additional comments (6)
typescript/warp-monitor/package.json (2)
1-59: Overall package structure looks solid.The manifest is well-structured with proper metadata, engine constraints, and the bundle script correctly excludes the dynamically-imported GCP logging package. Scripts align with the Docker build flow and the dependency patterns follow monorepo conventions.
22-22: The catalog setup here is already locked down right—@hyperlane-xyz/registryis pinned to23.7.0in the catalog definition, so thecatalog:reference resolves to that exact version and won't drift unexpectedly. No changes needed.typescript/warp-monitor/Dockerfile (4)
1-21: Builder base setup looks good.The slim image with foundry installation, corepack setup, and architecture-aware binary selection is solid. Using a pinned foundry version as an ARG gives you reproducibility while keeping flexibility.
29-43: Selective package.json copying is efficient.Copying just the package manifests needed for warp-monitor before
pnpm installtakes advantage of Docker layer caching—changes to source files won't invalidate the dependency installation layer. Smart move for faster rebuilds.
46-63: Build flow aligns with the bundle strategy.Source files are copied after dependency installation, and the turbo bundle command produces the ncc output. This matches the package.json bundle script that outputs to
./bundleand handles the external GCP logging package.
78-88: Production runtime configuration is appropriate.Alpine base keeps the image tiny, environment variables are sensible defaults, port 9090 is exposed for metrics scraping, and the CMD runs the bundled service. Clean setup for the production stage.
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🕵️ Warp Monitor Docker Image Built SuccessfullyImage Tags: |
🐳 Monorepo Docker Image Built SuccessfullyImage Tags: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7653 +/- ##
=======================================
Coverage 77.02% 77.02%
=======================================
Files 117 117
Lines 2651 2651
Branches 244 244
=======================================
Hits 2042 2042
Misses 593 593
Partials 16 16
🚀 New features to boost your workflow:
|
Summary
Image Size Comparison
Production Impact
With 181 warp monitors running across 19 nodes in mainnet3:
Approach
Uses @vercel/ncc to bundle the warp-monitor into a single file with all dependencies, then runs on a minimal Alpine image. This eliminates the need for pnpm/node_modules in the final image.
Follows the same pattern as the rebalancer standalone image (#7545).
Changes
New Package:
@hyperlane-xyz/warp-monitortypescript/warp-monitor/- New standalone packagetypescript/warp-monitor/Dockerfile- Multi-stage Docker build with ncc bundlingtypescript/warp-monitor/package.json- Added ncc and bundle scripttypescript/warp-monitor/scripts/ncc.post-bundle.mjs- Post-bundle __dirname fixtypescript/warp-monitor/turbo.json- Bundle tasktypescript/warp-monitor/src/service.ts- Service entry point using env vars:WARP_ROUTE_ID- RequiredREGISTRY_URI- Optional, supports/tree/{commit}formatCHECK_FREQUENCY- Optional (default 30000ms)COINGECKO_API_KEY- OptionalCI/CD
.github/workflows/warp-monitor-docker.yml- CI workflow for building/pushingHelm Chart Updates
typescript/infra/helm/warp-routes/- Updated to use standalone image and env varsgcr.io/abacus-labs-dev/hyperlane-warp-monitorregistryUriinstead ofregistryCommitCleanup
typescript/infra/scripts/warp-routes/monitor/Metrics Compatibility
All Prometheus metrics are 100% identical to the old implementation:
hyperlane_warp_route_token_balance✅hyperlane_warp_route_collateral_value✅hyperlane_warp_route_value_at_risk✅hyperlane_wallet_balance✅hyperlane_xerc20_limits✅Grafana dashboards will work seamlessly without changes.
Test plan
pnpm installsucceedspnpm lint:catalogpassespnpm buildsucceedsoUSDT/productionroute - metrics collected across 24+ chains🐳 Standalone Image Initiative
This PR is part of a wider effort to migrate TypeScript workloads from the 6.39 GB monorepo image to lightweight standalone images:
*20 unique nodes (some overlap between workloads)
Total Infrastructure Savings
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.
Greptile Summary
@hyperlane-xyz/warp-monitorpackage with Docker image that reduces deployment size from 6.39 GB to 227 MB (28x reduction) using ncc bundling, targeting 181 warp monitor pods across 19 nodes for significant infrastructure savingstypescript/infra/scripts/warp-routes/monitor/while maintaining 100% Prometheus metrics compatibility with existing Grafana dashboardsImportant Files Changed
typescript/warp-monitor/src/monitor.tstypescript/warp-monitor/src/metrics.tstypescript/warp-monitor/Dockerfiletypescript/infra/helm/warp-routes/templates/_helpers.tpl.github/workflows/warp-monitor-docker.ymlConfidence score: 4/5
typescript/warp-monitor/src/monitor.tsandtypescript/warp-monitor/src/metrics.tsfor monitoring logic correctness and Prometheus metric compatibilitySequence Diagram
sequenceDiagram participant User participant Service as "Warp Monitor Service" participant Registry participant WarpMonitor participant MetricsServer as "Metrics Server" participant WarpCore participant CoinGecko as "CoinGecko API" participant TokenAdapter as "Token Adapters" participant PrometheusClient as "Prometheus Client" User->>Service: "Start warp monitor service" Service->>Service: "Parse environment variables" Service->>Registry: "Initialize registry" Registry-->>Service: "Registry instance" Service->>WarpMonitor: "Create monitor instance" WarpMonitor->>MetricsServer: "Start metrics server on port 9090" MetricsServer-->>WarpMonitor: "Server started" WarpMonitor->>Registry: "Get chain metadata and addresses" Registry-->>WarpMonitor: "Chain data" WarpMonitor->>Registry: "Get warp route config" Registry-->>WarpMonitor: "Warp route config" WarpMonitor->>WarpCore: "Create WarpCore from config" WarpCore-->>WarpMonitor: "WarpCore instance" loop "Every CHECK_FREQUENCY interval" WarpMonitor->>WarpCore: "Get tokens from warp route" WarpCore-->>WarpMonitor: "Token list" loop "For each token" WarpMonitor->>TokenAdapter: "Get bridged balance" TokenAdapter-->>WarpMonitor: "Balance data" WarpMonitor->>CoinGecko: "Get token price" CoinGecko-->>WarpMonitor: "USD price" WarpMonitor->>PrometheusClient: "Update token balance metrics" alt "Token is xERC20" WarpMonitor->>TokenAdapter: "Get xERC20 limits" TokenAdapter-->>WarpMonitor: "Mint/burn limits" WarpMonitor->>PrometheusClient: "Update xERC20 limit metrics" end alt "Token is Sealevel" WarpMonitor->>TokenAdapter: "Get ATA payer balance" TokenAdapter-->>WarpMonitor: "Native balance" WarpMonitor->>PrometheusClient: "Update wallet balance metrics" end end endContext used:
dashboard- CLAUDE.md (source)