diff --git a/cli/src/commands/token-transfer.ts b/cli/src/commands/token-transfer.ts index 736bd63c4..0a3f467c0 100644 --- a/cli/src/commands/token-transfer.ts +++ b/cli/src/commands/token-transfer.ts @@ -39,9 +39,13 @@ import type { Ntt, NttWithExecutor, } from "@wormhole-foundation/sdk-definitions-ntt"; -import "@wormhole-foundation/sdk-evm-ntt"; -import "@wormhole-foundation/sdk-solana-ntt"; -import "@wormhole-foundation/sdk-sui-ntt"; +import { register as registerEvm } from "@wormhole-foundation/sdk-evm-ntt"; +import { register as registerSolana } from "@wormhole-foundation/sdk-solana-ntt"; +import { register as registerSui } from "@wormhole-foundation/sdk-sui-ntt"; + +registerEvm(); +registerSolana(); +registerSui(); import { loadConfig, type ChainConfig, type Config } from "../deployments"; import fs from "fs"; import readline from "readline"; diff --git a/cli/src/index.ts b/cli/src/index.ts index b0ab6f6be..5f63546b5 100755 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -5,10 +5,13 @@ import type { WormholeConfigOverrides } from "@wormhole-foundation/sdk-connect"; import fs from "fs"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; -import "@wormhole-foundation/sdk-evm-ntt"; -import "@wormhole-foundation/sdk-solana-ntt"; -import "@wormhole-foundation/sdk-sui-ntt"; -import "@wormhole-foundation/sdk-definitions-ntt"; +import { register as registerEvm } from "@wormhole-foundation/sdk-evm-ntt"; +import { register as registerSolana } from "@wormhole-foundation/sdk-solana-ntt"; +import { register as registerSui } from "@wormhole-foundation/sdk-sui-ntt"; + +registerEvm(); +registerSolana(); +registerSui(); import { createTokenTransferCommand } from "./commands/token-transfer"; import { diff --git a/evm/ts/src/index.ts b/evm/ts/src/index.ts index 41a239c28..bc8e44261 100644 --- a/evm/ts/src/index.ts +++ b/evm/ts/src/index.ts @@ -9,13 +9,11 @@ import { EvmMultiTokenNtt } from "./multiTokenNtt.js"; import { EvmMultiTokenNttWithExecutor } from "./multiTokenNttWithExecutor.js"; import { register as registerDefinitions } from "@wormhole-foundation/sdk-definitions-ntt"; +let _explicitlyRegistered = false; + /** Explicitly register EVM NTT protocols. Idempotent — safe to call multiple times. */ -export function register(topLevel = false): void { - if (topLevel) { - console.warn( - "@wormhole-foundation/sdk-evm-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." - ); - } +export function register(_deprecatedTopLevel?: boolean): void { + _explicitlyRegistered = true; registerDefinitions(); if (!protocolIsRegistered(_platform, "Ntt")) { registerProtocol(_platform, "Ntt", EvmNtt); @@ -35,9 +33,17 @@ export function register(topLevel = false): void { } } -// Backward-compatible: auto-register on import +// Backward-compatible: auto-register on import. +// Deferred so that consumers who call register() explicitly don't see the warning. // TODO: remove this next time we are cool with a major version bump and are OK requiring integrators to make code changes -register(true); +setTimeout(() => { + if (!_explicitlyRegistered) { + console.warn( + "@wormhole-foundation/sdk-evm-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." + ); + } + register(); +}, 0); export * as ethers_contracts from "./ethers-contracts/index.js"; export * from "./ntt.js"; diff --git a/sdk/definitions/__tests__/registerWarning.test.ts b/sdk/definitions/__tests__/registerWarning.test.ts new file mode 100644 index 000000000..4f46c91e6 --- /dev/null +++ b/sdk/definitions/__tests__/registerWarning.test.ts @@ -0,0 +1,38 @@ +describe("definitions register warning behavior", () => { + let warnSpy: jest.SpyInstance; + + beforeEach(() => { + jest.resetModules(); + jest.useFakeTimers(); + warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {}); + }); + + afterEach(() => { + jest.runOnlyPendingTimers(); + jest.useRealTimers(); + warnSpy.mockRestore(); + }); + + test("does not warn when register() is called explicitly", async () => { + await jest.isolateModulesAsync(async () => { + const mod = await import("../src/index.js"); + mod.register(); + }); + + jest.runOnlyPendingTimers(); + expect(warnSpy).not.toHaveBeenCalled(); + }); + + test("warns when relying on side-effect import auto-registration", async () => { + await jest.isolateModulesAsync(async () => { + await import("../src/index.js"); + }); + + jest.runOnlyPendingTimers(); + expect(warnSpy).toHaveBeenCalledWith( + expect.stringContaining( + "@wormhole-foundation/sdk-definitions-ntt: auto-registration on import is deprecated." + ) + ); + }); +}); diff --git a/sdk/definitions/src/index.ts b/sdk/definitions/src/index.ts index 8d3f62d96..4c0ef9cd9 100644 --- a/sdk/definitions/src/index.ts +++ b/sdk/definitions/src/index.ts @@ -8,13 +8,11 @@ import { nttNamedPayloads, } from "./layouts/index.js"; +let _explicitlyRegistered = false; + /** Explicitly register NTT payload types. Idempotent — safe to call multiple times. */ -export function register(topLevel = false): void { - if (topLevel) { - console.warn( - "@wormhole-foundation/sdk-definitions-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." - ); - } +export function register(_deprecatedTopLevel?: boolean): void { + _explicitlyRegistered = true; if (!payloadFactory.has(composeLiteral("Ntt", nttNamedPayloads[0]![0]))) { registerPayloadTypes("Ntt", nttNamedPayloads); } @@ -27,9 +25,17 @@ export function register(topLevel = false): void { } } -// Backward-compatible: auto-register on import +// Backward-compatible: auto-register on import. +// Deferred so that consumers who call register() explicitly don't see the warning. // TODO: remove this next time we are cool with a major version bump and are OK requiring integrators to make code changes -register(true); +setTimeout(() => { + if (!_explicitlyRegistered) { + console.warn( + "@wormhole-foundation/sdk-definitions-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." + ); + } + register(); +}, 0); export * from "./ntt.js"; export * from "./nttWithExecutor.js"; diff --git a/solana/ts/sdk/index.ts b/solana/ts/sdk/index.ts index 6b236f611..dc6740a50 100644 --- a/solana/ts/sdk/index.ts +++ b/solana/ts/sdk/index.ts @@ -8,13 +8,11 @@ import { SolanaNttWithExecutor } from "./nttWithExecutor.js"; import { register as registerDefinitions } from "@wormhole-foundation/sdk-definitions-ntt"; import "./side-effects"; +let _explicitlyRegistered = false; + /** Explicitly register Solana NTT protocols. Idempotent — safe to call multiple times. */ -export function register(topLevel = false): void { - if (topLevel) { - console.warn( - "@wormhole-foundation/sdk-solana-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." - ); - } +export function register(_deprecatedTopLevel?: boolean): void { + _explicitlyRegistered = true; registerDefinitions(); if (!protocolIsRegistered(_platform, "Ntt")) { registerProtocol(_platform, "Ntt", SolanaNtt); @@ -24,9 +22,17 @@ export function register(topLevel = false): void { } } -// Backward-compatible: auto-register on import +// Backward-compatible: auto-register on import. +// Deferred so that consumers who call register() explicitly don't see the warning. // TODO: remove this next time we are cool with a major version bump and are OK requiring integrators to make code changes -register(true); +setTimeout(() => { + if (!_explicitlyRegistered) { + console.warn( + "@wormhole-foundation/sdk-solana-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." + ); + } + register(); +}, 0); export * from "./ntt.js"; export * from "./nttWithExecutor.js"; diff --git a/sui/ts/src/index.ts b/sui/ts/src/index.ts index a87aa050c..e50e06370 100644 --- a/sui/ts/src/index.ts +++ b/sui/ts/src/index.ts @@ -7,13 +7,11 @@ import { SuiNtt } from "./ntt.js"; import { SuiNttWithExecutor } from "./nttWithExecutor.js"; import { register as registerDefinitions } from "@wormhole-foundation/sdk-definitions-ntt"; +let _explicitlyRegistered = false; + /** Explicitly register Sui NTT protocols. Idempotent — safe to call multiple times. */ -export function register(topLevel = false): void { - if (topLevel) { - console.warn( - "@wormhole-foundation/sdk-sui-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." - ); - } +export function register(_deprecatedTopLevel?: boolean): void { + _explicitlyRegistered = true; registerDefinitions(); if (!protocolIsRegistered(_platform, "Ntt")) { registerProtocol(_platform, "Ntt", SuiNtt); @@ -23,9 +21,17 @@ export function register(topLevel = false): void { } } -// Backward-compatible: auto-register on import +// Backward-compatible: auto-register on import. +// Deferred so that consumers who call register() explicitly don't see the warning. // TODO: remove this next time we are cool with a major version bump and are OK requiring integrators to make code changes -register(true); +setTimeout(() => { + if (!_explicitlyRegistered) { + console.warn( + "@wormhole-foundation/sdk-sui-ntt: auto-registration on import is deprecated. Import { register } and call it explicitly." + ); + } + register(); +}, 0); export * from "./ntt.js"; export * from "./nttWithExecutor.js";