Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds numeric formatting/validation utilities, deployment config error checking, and inbound-limit collection/configuration flows; integrates them into the CLI and enhances prompts with SIGINT abort handling. Extensive tests for formatting, config errors, and inbound-limit logic are added. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant Collector as InboundCollector
participant Validator as LimitFormatting
participant Prompt as Prompts
participant Config as Deployments
User->>CLI: add-chain / pull
CLI->>Collector: collectMissingInboundGroups(newChain?)
Collector->>Validator: checkNumberFormatting(outbound/inbound)
Validator-->>Collector: valid / invalid
Collector-->>CLI: MissingInboundGroup[]
alt groups found
CLI->>Prompt: if not skipPrompts -> ask for values
Prompt->>User: prompt for inbound limit
User-->>Prompt: enter value
Prompt->>Validator: isValidLimit(value, decimals)
Validator-->>Prompt: valid/invalid
Prompt-->>CLI: validated limits
CLI->>Config: setInboundLimit(...) per source/destination
else skipPrompts
CLI->>CLI: warn about missing inbound limits
end
CLI-->>User: complete (updated? hadMissing?)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. 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: 1
🤖 Fix all issues with AI agents
In `@cli/src/limitFormatting.ts`:
- Around line 1-9: formatNumber currently treats the minus sign as part of the
digit string, producing malformed output for negative bigints; update
formatNumber to detect negativity (e.g., check num < 0n), store the sign
separately, convert and operate on the absolute value (use -num for the abs),
then run the existing padding/splitting logic on the absolute value (variables:
num, str, padded, splitIndex) and finally prepend the stored sign to the
returned string (also handle the decimals === 0 case by returning
`${sign}${str}.`).
🧹 Nitpick comments (6)
cli/src/prompts.ts (1)
29-36: Minor code path clarity issue in SIGINT handler.When
abortOnSigintis true,process.exit(130)terminates immediately, making lines 34-35 unreachable in that branch. While functionally harmless, the code flow would be clearer with an early return or else block.♻️ Optional: Make control flow explicit
rl.once("SIGINT", () => { process.stdout.write("\n"); if (abortOnSigint) { process.exit(130); + return; // Unreachable but clarifies intent } settle(""); rl.close(); });cli/__tests__/limitFormatting.test.ts (2)
8-14: Consider adding edge case tests for negative bigints.The
formatNumberfunction acceptsbigintwhich can be negative. The current tests only cover non-negative values. If negative values are not expected, consider documenting this constraint; otherwise, add test cases to verify behavior.// Example test cases to consider: expect(formatNumber(-1234n, 2)).toBe("-12.34"); // or should this throw?
53-58: Consider testing edge case: empty string.The
isZeroLimitfunction returnstruefor empty strings (after removing dots,normalized.length === 0). If this is intentional behavior, consider adding an explicit test case to document it.// Add to clarify expected behavior: expect(isZeroLimit("")).toBe(true); // Is this intended? expect(isZeroLimit(".")).toBe(true); // Only a dotcli/src/limitFormatting.ts (1)
19-22: Redundant undefined check.After verifying
parts.length !== 2, accessingparts[1]is guaranteed to exist. Theundefinedcheck on line 20 is redundant. This is a minor style nit - the code is functionally correct.♻️ Optional: Simplify by removing redundant check
export function checkNumberFormatting( formatted: string, decimals: number ): boolean { const parts = formatted.split("."); if (parts.length !== 2) { return false; } - const fraction = parts[1]; - if (fraction === undefined) { - return false; - } - if (fraction.length !== decimals) { - return false; - } - return true; + return parts[1]!.length === decimals; }cli/src/limits.ts (2)
87-144: Consider extracting shared logic between collection functions.
collectMissingInboundGroupsandcollectMissingInboundGroupsForAllshare significant code (chain validation, outbound limit checking, grouping logic). The main difference is the filtering predicate. Consider extracting a common helper to reduce duplication.♻️ Optional: Extract shared logic
// Example shared helper approach: function collectMissingInboundGroupsCore( chainsConfig: Config["chains"], shouldIncludePair: (source: Chain, destination: Chain) => boolean ): MissingInboundGroup[] { // ... shared validation and grouping logic // Use shouldIncludePair to filter pairs } export function collectMissingInboundGroups(chainsConfig, newChain) { return collectMissingInboundGroupsCore(chainsConfig, (src, dst) => src === newChain || dst === newChain ); } export function collectMissingInboundGroupsForAll(chainsConfig) { return collectMissingInboundGroupsCore(chainsConfig, () => true); }
157-159: Placeholder outbound limit format may cause inconsistency.The placeholder
"0.0"(1 decimal) may not match the decimal precision expected by other chains. IfsetInboundLimitis ever called without an existing outbound limit configured, this could create format inconsistencies. The comment acknowledges this is a fallback, but consider documenting the expected caller invariant more explicitly or using a format that matches the source chain's decimals.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@cli/src/configErrors.ts`:
- Line 1: The file fails CI due to Prettier formatting; run the formatter and
commit the updated file so imports and spacing match project style.
Specifically, run the project's formatter command (e.g., `bun run prettier`) and
stage the resulting changes for this file (which contains the import of
assertChain and Chain from "@wormhole-foundation/sdk") so the import line and
overall file formatting conform to Prettier rules.
🧹 Nitpick comments (2)
cli/src/limits.ts (2)
97-99: Placeholder outbound"0.0"has a hardcoded 1-decimal format.If this fallback is ever reached, the outbound limit format won't match the destination's actual decimals, which would then fail
checkNumberFormattinginconfigErrors.ts. The comment acknowledges this is unlikely, but a more defensive approach would derive the format from the destination's known decimals.♻️ Suggested improvement
- destinationConfig.limits = { outbound: "0.0", inbound: {} }; + // Use a zero outbound matching the destination's expected decimal count. + // This path is defensive; normal flows only call setInboundLimit when outbound exists. + destinationConfig.limits = { outbound: "0.", inbound: {} };Though even
"0."(0 decimals) is arbitrary. Consider passingdecimalsintosetInboundLimitand usingformatNumber(0n, decimals)for a correct placeholder.
175-201: Per-source prompt loop is correct but consider a max-retry guard.The
while (true)on line 176 loops until valid input or Ctrl+C (viaabortOnSigint). This is standard for interactive CLI prompts, but in automated/scripted contexts where stdin is piped, a non-matching input could loop indefinitely. SinceskipPromptsguards the outer path, this is low risk.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@cli/src/configErrors.ts`:
- Line 4: The import statement for the Deployment type in configErrors.ts uses a
bare "./validation" path which will fail under ESM resolution; update the import
to reference the emitted module file by changing the specifier to
"./validation.js" (i.e., modify the import that brings in Deployment) and search
for other occurrences of "from './validation'" in the codebase to make the same
change so runtime ESM resolution succeeds.
Manually integrate changes from two PRs merged to main into the restructured module layout: PR #808 — Inbound limit prompts: - Add limitFormatting.ts, limits.ts, configErrors.ts modules - Add interactive inbound limit prompts to add-chain and pull commands - Add abortOnSigint support to prompts.ts - Add --yes flag to sepolia-bsc.sh test script PR #809 — Bounded concurrency: - Add utils/concurrency.ts (runTaskPool, runTaskPoolWithSequential) - Parallelize pullDeployments, pullInboundLimits, collectMissingConfigs - Return { deps, failures } from pullDeployments with failure handling - Add --rpc-concurrency option to clone/pull/status commands - Add concurrent peer discovery with progress UI to clone command Also updates CI with test-cli-unit job and test format expectations to match full-precision limit formatting.
* Add EVM v2.0.0 SDK bindings
- Update NttManager version to 2.0.0
- Update WormholeTransceiver version to 2.0.0
- Generate TypeScript ABI bindings for v2.0.0
- Update SDK to support v2.0.0 contract ABI
* fixed AbiBindings
* test: add bun test infrastructure for CLI
* test: add functional tests for CLI (help output, module exports, utilities)
- cli-help.test.ts: verifies all commands and subcommands appear in --help
- module-exports.test.ts: verifies all modules can be imported with correct shapes
- utils.test.ts: tests diffObjects, colorizeDiff, and colors utilities
- 2 tests skipped due to known circular dep (configuration.ts <-> index.ts)
* refactor: move ensureNttRoot to validation.ts, fix circular dependency
configuration.ts was importing ensureNttRoot from index.ts, creating a
circular dependency that prevented module-level testing. Now imports
from validation.ts directly. index.ts re-exports for backwards compat.
* refactor: extract shared options, types, and constants to commands/shared.ts
Moves options, CclConfig, SuiDeploymentResult, EXCLUDED_DIFF_PATHS,
CCL_CONTRACT_ADDRESSES, getNestedValue, and setNestedValue out of
index.ts into commands/shared.ts for reuse by extracted commands.
* refactor: extract all CLI commands to individual files in commands/
- Create 15 command files in cli/src/commands/ (add-chain, clone, config,
hype, init, manual, new, pull, push, set-mint-authority, solana, status,
transfer-ownership, update, upgrade)
- Create barrel file (commands/index.ts) re-exporting all command creators
- Export 19 functions from index.ts needed by extracted command files
- Add tests for commands/shared.ts exports and safe command creators
* refactor: wire extracted commands into yargs chain, replace 2150+ inline lines
- Replace inline yargs .command() chain with imports from commands/
- index.ts reduced from 5494 to 3240 lines
- Update help tests to run local CLI via Bun.spawn instead of global binary
- Add hype subcommand test
- All 35 tests pass, CLI help output verified for all commands
* fix: add missing return in builder functions for solana, hype, manual commands
Fixes 3 TypeScript errors where builder functions returned void instead
of the yargs instance. These errors also existed in the original inline
code before extraction.
* refactor: remove unused imports from index.ts after command extraction
Remove enableBigBlocks, hasExecutorDeployed, isNetwork, networks,
platforms, getNestedValue, setNestedValue - all now only used in their
respective command files.
* fix: wire 1.3.1 ABI bindings and fix CCL type errors in getImmutables
- Add 1_3_1 ethers contract bindings to ethers-contracts/index.ts and
bindings.ts abiVersions (was on disk but not wired in)
- Fix TypeScript errors for customConsistencyLevel, additionalBlocks,
customConsistencyLevelAddress by using a typed cast in the try/catch
block (these methods only exist on contracts >= v1.3.1)
- tsc --noEmit now passes with zero errors
* refactor: clean up unused imports in index.ts
Remove 15 unused imports left over after command extraction:
RpcConnection, myEvmSigner, $, AddressLookupTableAccount,
SendTransactionError, TransactionMessage, VersionedTransaction,
UniversalAddress, bcs, Interface, loadConfig, collectMissingConfigs,
printMissingConfigReport, promptSolanaMainnetOverridesIfNeeded,
validatePayerOption. Add TODO for CCL type cast.
* refactor: remove stale comment in index.ts
* refactor: extract query/utility functions to query.ts
Move getImmutables, getPdas, getVersion, nttFromManager, formatNumber,
checkNumberFormatting, and pullInboundLimits into a separate query.ts
module. Re-export from index.ts for backward compatibility.
* refactor: extract EVM and Solana helpers to dedicated modules
Move EVM deployment helpers (withDeploymentScript, detectDeployScriptVersion,
supportsManagerVariants, getSlowFlag, getGasMultiplier, buildVerifierArgs)
to evm-helpers.ts and Solana build/binary helpers (patchSolanaBinary,
checkSvmBinary, checkSolanaVersion, checkAnchorVersion, cargoNetworkFeature,
hasBridgeAddressFromEnvFeature, checkSvmValidSplMultisig) to solana-helpers.ts.
* test: add unit, integration, and E2E tests for CLI modules
- cli-commands.test.ts: help output tests for all 16 subcommands
- e2e-anvil.test.ts: full NTT deploy flow on Anvil forks (Sepolia + Base Sepolia)
- evm-helpers.test.ts: detectDeployScriptVersion, getSlowFlag, getGasMultiplier, buildVerifierArgs
- query.test.ts: formatNumber, checkNumberFormatting
- solana-helpers.test.ts: cargoNetworkFeature, hasBridgeAddressFromEnvFeature
- validation.test.ts: ensureNttRoot
* ci: share forge build cache from EVM workflow to CLI E2E tests
- evm.yml: add forge build --via-ir + actions/cache/save after tests
- cli.yml: replace Docker-based test-evm with native runner (foundry v1.5.0,
bun v1.3.4) and restore forge cache via actions/cache/restore
- index.ts: add seedForgeCache() to copy cached artifacts into worktree evm/
directories in deployEvm and upgradeEvm when NTT_EVM_CACHE_DIR is set
- .gitignore: exclude docs/plans/
* fix(test): resolve CLI path and skip E2E when anvil unavailable
- cli-commands.test.ts: use path.resolve from import.meta.dir instead
of relative path that breaks when CWD is cli/ (as in ts-sdk-ci)
- e2e-anvil.test.ts: skip test suite when anvil is not in PATH
* refactor: group chain-specific files into evm/, solana/, sui/, signers/ subdirectories
Move chain-specific helpers, signers, and utilities into dedicated
subdirectories for better organization. Also moves tokenTransfer.ts
into commands/ where it belongs as a command factory.
File moves:
- evm-helpers.ts, evmsigner.ts, hyperliquid.ts → evm/
- solana-helpers.ts, solanaHelpers.ts → solana/
- suisigner.ts → sui/
- getSigner.ts, signSendWait.ts → signers/
- tokenTransfer.ts → commands/token-transfer.ts
* refactor: extract remaining functions from index.ts into dedicated modules
Move all business logic out of index.ts (2597 → 141 lines), leaving only
the yargs command chain, nttVersion(), and re-exports for backward
compatibility.
New files:
- deploy.ts: deploy/upgrade dispatchers
- config-mgmt.ts: pushDeployment, pullDeployments, pullChainConfig
- evm/deploy.ts: deployEvm, upgradeEvm
- solana/deploy.ts: runAnchorBuild, buildSvm, deploySvm, upgradeSolana
- sui/deploy.ts: deploySui, upgradeSui
- sui/helpers.ts: withSuiEnv, updateMoveTomlForNetwork, performPackageUpgradeInPTB
Functions moved to existing files:
- askForConfirmation → prompts.ts
- parseCclFlag, confirmCustomFinality → commands/shared.ts
- validateChain, checkConfigErrors → validation.ts
- seedForgeCache → evm/helpers.ts
- resolveVersion, createWorkTree, warnLocalDeployment → tag.ts
The module-level `overrides` variable is now threaded as an explicit
parameter through pullDeployments, runAnchorBuild, buildSvm, deploy,
upgrade, and pushDeployment instead of being captured from module scope.
* style: fix prettier formatting in new modules
* fix CCL type cast using the same pattern from the sdk
* fix: resolve 8 preexisting bugs found by CodeRabbit review
- Replace hand-rolled formatNumber/checkNumberFormatting with ethers
formatUnits/parseUnits, and BigInt(str.replace(".","")) with parseUnits
- Add missing process.exit(1) in set-mint-authority catch block
- Invert multisig validation at second call site (undeployed case)
- Fix --yes flag fallthrough for undeployed programs in solana.ts
- Pass undefined instead of evmVerify to deploySui, add block scoping
- Guard chainConf.limits before accessing .inbound in pullInboundLimits
- Replace execSync with execFileSync for sui keytool (no shell injection)
- Fix Sepolia counterpart check variable (c -> chain) in validateChain
* fix: resolve more preexisting bugs
* test: add regression tests for config validation and chain detection
* feat: integrate PR #808 (inbound limits) and PR #809 (parallelization)
Manually integrate changes from two PRs merged to main into the
restructured module layout:
PR #808 — Inbound limit prompts:
- Add limitFormatting.ts, limits.ts, configErrors.ts modules
- Add interactive inbound limit prompts to add-chain and pull commands
- Add abortOnSigint support to prompts.ts
- Add --yes flag to sepolia-bsc.sh test script
PR #809 — Bounded concurrency:
- Add utils/concurrency.ts (runTaskPool, runTaskPoolWithSequential)
- Parallelize pullDeployments, pullInboundLimits, collectMissingConfigs
- Return { deps, failures } from pullDeployments with failure handling
- Add --rpc-concurrency option to clone/pull/status commands
- Add concurrent peer discovery with progress UI to clone command
Also updates CI with test-cli-unit job and test format expectations
to match full-precision limit formatting.
* test: consolidate tests and move E2E to cli/e2e/
- Merge cli-commands.test.ts into cli-help.test.ts with a maintained
EXPECTED_COMMANDS list instead of one test per command
- Move E2E test to cli/e2e/ so unit tests (bun run test) exclude it;
remove skip logic, require anvil with clear error message
- Consolidate evm-helpers tests (8 individual → 2 data-driven)
- Consolidate module-exports tests (14 individual → 7 grouped)
- Suppress console.error noise in checkConfigErrors tests
- Delete unused setup.ts
- Add test:e2e script to package.json
* fix: address CodeRabbit review feedback on E2E tests and CI
- Add NTT_EVM_CACHE_DIR env var to E2E CI step for forge cache reuse
- Validate anvil_setStorageAt response in setCoreBridgeFee
- Check cast send exit code in grantRoleImpersonated
- Fix timeout race in ntt() helper to kill hung processes
- Remove unused SEPOLIA_CCL_CONTRACT constant
* fix: address second round CodeRabbit feedback on tests
- Assert status command exit code in E2E test
- Check cast call exit code in role-verification loop
- Use non-null assertion for warnSpy in limits test
Clone of #794 by @martin0995
This pull request introduces a new system for configuring and validating inbound transfer limits between chains in the CLI deployment configuration. It adds interactive prompts to ensure that all required inbound limits are set (or warns if they are missing when prompts are skipped), improving deployment safety and user experience. The main changes are the addition of a new
limits.tsmodule, integration of inbound limit configuration into CLI commands, and enhancements to the prompt utilities.Inbound limits configuration and validation:
cli/src/limits.tsthat provides utilities to detect missing or zero inbound transfer limits between chains, prompt the user to set them (with validation), and update the deployment configuration accordingly. This includes logic to group missing limits, provide sensible defaults, and handle both new chain additions and configuration pulls.configureInboundLimitsForNewChainandconfigureInboundLimitsForPullinto the CLI command flow incli/src/index.ts, so that users are prompted to fill in missing inbound limits when adding a new chain or pulling configuration. The system can also warn when limits are missing and prompts are skipped (e.g., with--yes). [1] [2] [3]Prompt utility improvements:
cli/src/prompts.tsto support aborting on Ctrl+C (SIGINT), which now immediately exits with a specific code if enabled. This is used in the new inbound limits prompts for a better user experience. [1] [2]promptYesNoto accept the new abort option and to delegate it topromptLine, ensuring consistent behavior across prompts.Summary by CodeRabbit
New Features
Improvements
Tests
Chores