Skip to content

fix: silence NTT deprecation warnings when register() is called explicitly#834

Merged
evgeniko merged 1 commit intomainfrom
fix/sdk-register-deprecation-warning
Mar 6, 2026
Merged

fix: silence NTT deprecation warnings when register() is called explicitly#834
evgeniko merged 1 commit intomainfrom
fix/sdk-register-deprecation-warning

Conversation

@evgeniko
Copy link
Copy Markdown
Contributor

@evgeniko evgeniko commented Mar 6, 2026

Summary

  • update CLI to explicitly register NTT SDK integrations instead of side-effect imports
  • keep deprecation warnings for side-effect auto-registration, but defer fallback registration to setTimeout(..., 0) so explicit register() calls (including dynamic import flows) do not log false-positive warnings
  • keep register backward-compatible with an optional deprecated parameter signature
  • add a regression test in sdk-definitions to lock warning behavior (explicit register => no warning, side-effect import => warning)

Why

Running ntt --version was printing loud deprecation warnings even when consumers follow the explicit-registration migration path. This change preserves the deprecation signal for legacy usage while removing noise for correct usage.

Validation

  • ntt --version prints clean output without deprecation warnings
  • bun run typecheck:cli
  • bun run --filter "@wormhole-foundation/sdk-definitions-ntt" test -- __tests__/registerWarning.test.ts
  • dynamic import + explicit register smoke checks (evm/solana/sui) produce no warning

@evgeniko evgeniko marked this pull request as draft March 6, 2026 15:36
@evgeniko evgeniko marked this pull request as ready for review March 6, 2026 15:38
@evgeniko evgeniko requested a review from DBosley March 6, 2026 15:39
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

This PR refactors the SDK registration mechanism across multiple network implementations (EVM, Solana, Sui, Definitions) by replacing implicit side-effect imports with explicit named imports and deferred registration calls. The registration flow now tracks explicit invocations separately from auto-registration and reserves deprecation warnings for implicit use.

Changes

Cohort / File(s) Summary
CLI registration updates
cli/src/commands/token-transfer.ts, cli/src/index.ts
Replaced side-effect imports of NTT SDK modules with explicit named imports (registerEvm, registerSolana, registerSui) and added explicit registration calls at initialization.
SDK registration refactoring
evm/ts/src/index.ts, solana/ts/sdk/index.ts, sui/ts/src/index.ts, sdk/definitions/src/index.ts
Updated register() function signature from register(topLevel = false) to register(_deprecatedTopLevel?: boolean). Added internal _explicitlyRegistered flag to distinguish explicit calls from auto-registration. Deferred auto-registration via setTimeout with deprecation warnings emitted only when implicit auto-registration occurs.
Export expansion
evm/ts/src/index.ts, sdk/definitions/src/index.ts
Added re-exports for NTT-related modules: nttWithExecutor, multiTokenNtt, multiTokenNttWithExecutor, and additional utilities like trimmedAmount, axelar, and layouts (definitions only).
Registration behavior tests
sdk/definitions/__tests__/registerWarning.test.ts
Added new test suite verifying deprecation warning behavior: confirms warnings are suppressed on explicit register() calls but emitted on side-effect auto-registration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • kcsongor
  • kev1n-peters

Poem

🐰 Explicit paths we now embrace,
Side effects cleared from their place,
Register calls, no longer hide,
Deferred registration as our guide,
With warnings wise for those who slip,
The SDK's now got a firmer grip!

🚥 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 accurately summarizes the main change: silencing NTT deprecation warnings when register() is called explicitly, which is the core fix across all modified files.
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 (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/sdk-register-deprecation-warning

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 (3)
sdk/definitions/src/index.ts (1)

14-38: ⚠️ Potential issue | 🟠 Major

The deferred registration contradicts "Backward-compatible: auto-register on import."

setTimeout(..., 0) delays registerPayloadTypes(...) to the next macrotask. While the current test suite doesn't fail because all payload operations use async getProtocol() calls (which execute after the timer), the implementation still violates the stated guarantee: true import-time registration is synchronous, not deferred. Any consumer that performs synchronous payload operations immediately after import could encounter an empty factory.

The suggested fix is sound: register synchronously and defer only the warning by using the deprecated parameter to distinguish explicit calls from the internal fallback.

Possible fix shape
-export function register(_deprecatedTopLevel?: boolean): void {
-  _explicitlyRegistered = true;
+export function register(_deprecatedTopLevel = false): void {
+  if (!_deprecatedTopLevel) {
+    _explicitlyRegistered = true;
+  }
   if (!payloadFactory.has(composeLiteral("Ntt", nttNamedPayloads[0]![0]))) {
     registerPayloadTypes("Ntt", nttNamedPayloads);
   }
   if (
     !payloadFactory.has(
       composeLiteral("MultiTokenNtt", multiTokenNttNamedPayloads[0]![0])
     )
   ) {
     registerPayloadTypes("MultiTokenNtt", multiTokenNttNamedPayloads);
   }
 }
 
-setTimeout(() => {
-  if (!_explicitlyRegistered) {
-    console.warn(
-      "@wormhole-foundation/sdk-definitions-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly."
-    );
-  }
-  register();
-}, 0);
+register(true);
+setTimeout(() => {
+  if (!_explicitlyRegistered) {
+    console.warn(
+      "@wormhole-foundation/sdk-definitions-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly."
+    );
+  }
+}, 0);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sdk/definitions/src/index.ts` around lines 14 - 38, The register function
currently defers payload registration via setTimeout, causing import-time
registration to be asynchronous; change the behavior so register() is invoked
synchronously on import (call register() directly) while only deferring the
deprecation warning so callers who explicitly passed the deprecatedTopLevel flag
are not warned—use the existing _explicitlyRegistered flag and the
deprecatedTopLevel parameter to detect explicit calls (keep
registerPayloadTypes("Ntt", ...) and registerPayloadTypes("MultiTokenNtt", ...)
logic inside register) and move the console.warn into a deferred timer that runs
only when _explicitlyRegistered is false after performing the synchronous
register call.
sui/ts/src/index.ts (1)

13-34: ⚠️ Potential issue | 🟠 Major

Import-time registration timing has changed in a way that contradicts the backward-compatibility goal.

While the actual registerProtocol(...) calls are still executed before any real consumer code runs (since all protocol lookups are async), the registration is now deferred to a macrotask instead of happening synchronously during module initialization. This breaks the documented contract that protocols are available on import.

The previous implementation (commit c3774e0) called register(true) synchronously. The current deferred approach using setTimeout(..., 0) still works in practice because all SDK consumers use await chain.getProtocol(), but it violates the semantic promise of "auto-register on import" for anything that might synchronously check protocol availability during the same event tick.

If deprecating synchronous auto-registration is intentional, update the comment to clarify that the async deferral is permanent (not temporary), and consider whether the deprecation message is still accurate. If backward compatibility is required, restore synchronous registration while keeping only the warning deferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sui/ts/src/index.ts` around lines 13 - 34, The module currently defers
auto-registration via setTimeout which breaks the promise of synchronous
"auto-register on import"; restore backward-compatible behavior by invoking
register(true) synchronously during module initialization (use the existing
register(_deprecatedTopLevel?: boolean) API and pass true) and keep only the
deprecation warning deferred using setTimeout (so remove the deferred register()
call but retain the console.warn in the macrotask that checks
_explicitlyRegistered); alternatively, if the async deferral is intentional,
update the top comment and the warning to explicitly state that registration is
permanently deferred and adjust logic to avoid claiming "auto-register on
import" is supported (reference symbols: register, _explicitlyRegistered,
setTimeout, registerProtocol, protocolIsRegistered, SuiNtt, SuiNttWithExecutor).
solana/ts/sdk/index.ts (1)

14-35: ⚠️ Potential issue | 🟠 Major

Deferred fallback registration breaks import-time compatibility.

Moving the fallback register() behind setTimeout(..., 0) means Ntt / NttWithExecutor are no longer registered during module evaluation. Any existing consumer that imports this module and immediately uses SDK lookups in the same turn can now race the timer; solana/tests/anchor/anchor.test.ts is an in-repo example of that pattern. Please keep the fallback registration synchronous and defer only the warning, e.g. by using the deprecated parameter to distinguish internal auto-registration from explicit register() calls.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@solana/ts/sdk/index.ts` around lines 14 - 35, The deferred setTimeout
registration causes race conditions; make the auto-registration synchronous
while deferring only the warning: if _explicitlyRegistered is false call
register(true) immediately (so register can detect the deprecated internal
auto-registration via its _deprecatedTopLevel param and avoid re-triggering the
warning), and keep the setTimeout only for console.warn; update register to
respect the _deprecatedTopLevel flag (use _explicitlyRegistered and skip
emitting the deprecation warning when _deprecatedTopLevel is true) and ensure
protocolIsRegistered/registerProtocol/SolanaNtt/SolanaNttWithExecutor logic
remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@sdk/definitions/src/index.ts`:
- Around line 14-38: The register function currently defers payload registration
via setTimeout, causing import-time registration to be asynchronous; change the
behavior so register() is invoked synchronously on import (call register()
directly) while only deferring the deprecation warning so callers who explicitly
passed the deprecatedTopLevel flag are not warned—use the existing
_explicitlyRegistered flag and the deprecatedTopLevel parameter to detect
explicit calls (keep registerPayloadTypes("Ntt", ...) and
registerPayloadTypes("MultiTokenNtt", ...) logic inside register) and move the
console.warn into a deferred timer that runs only when _explicitlyRegistered is
false after performing the synchronous register call.

In `@solana/ts/sdk/index.ts`:
- Around line 14-35: The deferred setTimeout registration causes race
conditions; make the auto-registration synchronous while deferring only the
warning: if _explicitlyRegistered is false call register(true) immediately (so
register can detect the deprecated internal auto-registration via its
_deprecatedTopLevel param and avoid re-triggering the warning), and keep the
setTimeout only for console.warn; update register to respect the
_deprecatedTopLevel flag (use _explicitlyRegistered and skip emitting the
deprecation warning when _deprecatedTopLevel is true) and ensure
protocolIsRegistered/registerProtocol/SolanaNtt/SolanaNttWithExecutor logic
remains unchanged.

In `@sui/ts/src/index.ts`:
- Around line 13-34: The module currently defers auto-registration via
setTimeout which breaks the promise of synchronous "auto-register on import";
restore backward-compatible behavior by invoking register(true) synchronously
during module initialization (use the existing register(_deprecatedTopLevel?:
boolean) API and pass true) and keep only the deprecation warning deferred using
setTimeout (so remove the deferred register() call but retain the console.warn
in the macrotask that checks _explicitlyRegistered); alternatively, if the async
deferral is intentional, update the top comment and the warning to explicitly
state that registration is permanently deferred and adjust logic to avoid
claiming "auto-register on import" is supported (reference symbols: register,
_explicitlyRegistered, setTimeout, registerProtocol, protocolIsRegistered,
SuiNtt, SuiNttWithExecutor).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 218b6f00-6785-4853-aa46-99ab34390a30

📥 Commits

Reviewing files that changed from the base of the PR and between fee796a and 3b5c3db.

📒 Files selected for processing (7)
  • cli/src/commands/token-transfer.ts
  • cli/src/index.ts
  • evm/ts/src/index.ts
  • sdk/definitions/__tests__/registerWarning.test.ts
  • sdk/definitions/src/index.ts
  • solana/ts/sdk/index.ts
  • sui/ts/src/index.ts

@evgeniko evgeniko merged commit fcd7396 into main Mar 6, 2026
26 of 27 checks passed
@evgeniko evgeniko deleted the fix/sdk-register-deprecation-warning branch March 6, 2026 17:04
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