Skip to content

feat: add explicit register() exports for tree-shaking compatibility#825

Merged
DBosley merged 5 commits intomainfrom
feat/explicit-register
Feb 17, 2026
Merged

feat: add explicit register() exports for tree-shaking compatibility#825
DBosley merged 5 commits intomainfrom
feat/explicit-register

Conversation

@DBosley
Copy link
Copy Markdown
Contributor

@DBosley DBosley commented Feb 12, 2026

Summary

  • Add idempotent register() function exports to definitions, evm, solana, and sui NTT SDK packages
  • Consumers can now use named imports (import { register } from '...') instead of bare side-effect imports (import '...')
  • Named imports give bundlers (webpack/turbopack) a bound reference to preserve when sideEffects optimization is enabled
  • Module-scope auto-registration preserved for full backward compatibility — no breaking changes

Why

wormhole-connect's sideEffects field optimization causes webpack/turbopack to drop bare side-effect imports (import '@wormhole-foundation/sdk-evm-ntt'). With a named register() export, consumers create a bound import that bundlers preserve regardless of sideEffects settings.

Changes

File Change
sdk/definitions/src/index.ts Add register() wrapping registerPayloadTypes() calls
evm/ts/src/index.ts Add register() wrapping registerProtocol() calls + definitions registration
solana/ts/sdk/index.ts Add register() wrapping registerProtocol() calls + definitions registration
sui/ts/src/index.ts Add register() wrapping registerProtocol() calls + definitions registration

Backward Compatibility

Consumer pattern Before After
import "@wormhole-foundation/sdk-evm-ntt" (bare) Module loads → registrations execute Module loads → register() at module scope → same result
import { EvmNtt } from "@wormhole-foundation/sdk-evm-ntt" Module loads → registrations execute Module loads → register() at module scope → same result
import { register } from "..."; register() N/A (new) Module scope runs first (1st call), explicit register() is idempotent no-op

Test plan

  • bun run build — definitions, solana, sui compile. EVM has pre-existing ZeroGravity type error (unrelated)
  • register export confirmed in dist/esm/index.js for definitions, solana, sui
  • Existing tests pass (bun run test)
  • Downstream wormhole-connect build with named imports preserves registration calls in bundle

Summary by CodeRabbit

  • New Features

    • Added explicit, idempotent register(topLevel?: boolean) APIs and kept import-time auto-registration for backward compatibility across EVM, Solana, Sui, and SDK definitions.
    • Expanded public exports to include multi-token and executor variants, aggregated contract helpers, trimmed amount/axelar helpers, and layout types.
  • Bug Fixes

    • Prevented duplicate protocol/payload registrations by adding idempotent registration checks.

Add idempotent register() function exports to definitions, evm, solana,
and sui packages so consumers can use named imports instead of bare
side-effect imports. This gives bundlers (webpack/turbopack) a bound
import to preserve when sideEffects optimization is enabled.

Module-scope auto-registration is preserved for backward compatibility.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

Replaced top-level side-effect registrations with explicit, idempotent exported register() functions across EVM, SDK definitions, Solana, and Sui modules; each uses guards (protocolIsRegistered / payloadFactory) and delegates to imported registerDefinitions; still auto-invokes register() on import for backward compatibility.

Changes

Cohort / File(s) Summary
EVM implementation
evm/ts/src/index.ts
Added exported register(topLevel = false) that calls imported registerDefinitions, guards registerProtocol with protocolIsRegistered, auto-invokes register() at import, and re-exports additional NTT modules plus ethers_contracts.
SDK definitions
sdk/definitions/src/index.ts
Added exported register(topLevel = false) that conditionally registers payload types using payloadFactory/registerPayloadTypes and composeLiteral; replaced eager registration with guarded registration; auto-invokes register(true) at import; added exports for multiTokenNtt, multiTokenNttWithExecutor, trimmedAmount, axelar, and layouts (including layout types).
Solana implementation
solana/ts/sdk/index.ts
Added exported register() that imports registerDefinitions, uses protocolIsRegistered guards before registering Ntt/NttWithExecutor, and auto-invokes register() at import while preserving existing exports.
Sui implementation
sui/ts/src/index.ts
Added exported register(topLevel?: boolean) that calls registerDefinitions, guards protocol registration with protocolIsRegistered, moves registrations into register() with an import-time auto-invoke for compatibility, and preserves original exports.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped through lines of code tonight,
I wrapped each register so calls stay polite.
No double bells, just one neat ring,
Definitions tied, the modules sing —
Carrot builds for morning light. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add explicit register() exports for tree-shaking compatibility' directly and clearly summarizes the main change: adding explicit register() function exports across NTT SDK packages to enable tree-shaking compatibility.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/explicit-register

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
evm/ts/src/index.ts (1)

1-34: ⚠️ Potential issue | 🟡 Minor

Fix Prettier formatting issue flagged by CI.

The pipeline reports a code style violation in this file. Run prettier --write evm/ts/src/index.ts to resolve.

🧹 Nitpick comments (1)
solana/ts/sdk/index.ts (1)

5-21: The bare side-effect import on Line 6 is a valid concern — verify if it should be incorporated into register().

The import "./side-effects" on Line 6 contains critical runtime patches that suppress console warnings from native libraries (secp256k1 and bigint). This bare side-effect import could be tree-shaken away by bundlers configured with sideEffects: false, causing those warnings to unexpectedly appear in consumers' output.

Since this PR aims to move away from side-effect imports, either incorporate the side-effects module into the register() function to ensure it always runs when the SDK is initialized, or ensure the file is marked as non-tree-shakeable in the package configuration.

kcsongor
kcsongor previously approved these changes Feb 12, 2026
Check the actual SDK registry before attempting registration rather
than relying on a module-level _registered flag. This verifies the
protocols are actually registered, not just that the function ran.
Module-scope register() calls now emit console.warn when triggered
as a side effect of importing the package, nudging consumers to
import { register } and call it explicitly.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@evm/ts/src/index.ts`:
- Around line 38-40: The EVM package is auto-calling register(true) which causes
duplicate deprecation warnings when the definitions package (via
registerDefinitions()) has already performed its own register(true); update the
EVM top-level import logic to avoid emitting a second warning by replacing the
auto-call register(true) with a non-warning call or no-op: either remove the
module-scope register(true) call entirely or change it to register(false)/a
suppressed form so registerDefinitions() still runs but no duplicate deprecation
warning is logged; reference the symbols register(true) in this file and
registerDefinitions() to locate and modify the behavior.

In `@sdk/definitions/src/index.ts`:
- Around line 12-32: The unconditional auto-registration call register(true)
triggers the deprecation warning for every importer; change the auto-register
invocation to suppress the warning by calling register() or register(false)
instead, or alternatively wrap the register(true) call in a NODE_ENV check (e.g.
only call it when process.env.NODE_ENV !== 'production') so production consumers
aren't noisy; apply the same change to the equivalent auto-registration calls
that use register(true) across the other SDK entry points (the EVM, Solana and
Sui module entry files) to keep behavior consistent.

@DBosley DBosley merged commit c3774e0 into main Feb 17, 2026
25 of 29 checks passed
@DBosley DBosley deleted the feat/explicit-register branch February 17, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants