@dynamic-labs-sdk/legacy-embedded-wallet-upgrade 1.22.1 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/clearUpgradeRedirectParams/clearUpgradeRedirectParams.d.ts +34 -0
  2. package/dist/clearUpgradeRedirectParams/clearUpgradeRedirectParams.d.ts.map +1 -0
  3. package/dist/clearUpgradeRedirectParams/index.d.ts +2 -0
  4. package/dist/clearUpgradeRedirectParams/index.d.ts.map +1 -0
  5. package/dist/errors/UpgradePopupBlockedError.d.ts +5 -0
  6. package/dist/errors/UpgradePopupBlockedError.d.ts.map +1 -0
  7. package/dist/errors/UpgradePopupClosedError.d.ts +5 -0
  8. package/dist/errors/UpgradePopupClosedError.d.ts.map +1 -0
  9. package/dist/exports/index.d.ts +3 -0
  10. package/dist/exports/index.d.ts.map +1 -1
  11. package/dist/exports/react.d.ts +1 -0
  12. package/dist/exports/react.d.ts.map +1 -1
  13. package/dist/index.cjs +12 -10
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.esm.js +2 -2
  16. package/dist/index.esm.js.map +1 -1
  17. package/dist/index.native.esm.js +124 -3
  18. package/dist/index.native.esm.js.map +1 -1
  19. package/dist/openUpgradePopup/index.d.ts +3 -0
  20. package/dist/openUpgradePopup/index.d.ts.map +1 -0
  21. package/dist/openUpgradePopup/openUpgradePopup.d.ts +40 -0
  22. package/dist/openUpgradePopup/openUpgradePopup.d.ts.map +1 -0
  23. package/dist/openUpgradePopup/openUpgradePopup.types.d.ts +44 -0
  24. package/dist/openUpgradePopup/openUpgradePopup.types.d.ts.map +1 -0
  25. package/dist/{subscribeToUpgradeCompletion-BuoizMF2.esm.js → openUpgradePopup-DNe06for.esm.js} +151 -4
  26. package/dist/openUpgradePopup-DNe06for.esm.js.map +1 -0
  27. package/dist/{subscribeToUpgradeCompletion-CjqiLYs5.cjs → openUpgradePopup-DuGh1T8k.cjs} +159 -6
  28. package/dist/openUpgradePopup-DuGh1T8k.cjs.map +1 -0
  29. package/dist/react/useUpgradePopup/index.d.ts +2 -0
  30. package/dist/react/useUpgradePopup/index.d.ts.map +1 -0
  31. package/dist/react/useUpgradePopup/useUpgradePopup.d.ts +93 -0
  32. package/dist/react/useUpgradePopup/useUpgradePopup.d.ts.map +1 -0
  33. package/dist/react/useUpgradeRedirectResult/useUpgradeRedirectResult.d.ts.map +1 -1
  34. package/dist/react.cjs +101 -13
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.esm.js +97 -10
  37. package/dist/react.esm.js.map +1 -1
  38. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  39. package/package.json +6 -6
  40. package/dist/subscribeToUpgradeCompletion-BuoizMF2.esm.js.map +0 -1
  41. package/dist/subscribeToUpgradeCompletion-CjqiLYs5.cjs.map +0 -1
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Removes the upgrade outcome parameter (`dynamicWaasMigrationStatus`) that the
3
+ * upgrade app appends to the return URL from the browser's current URL, leaving
4
+ * every other query parameter, the path, and the hash untouched.
5
+ *
6
+ * Call this once you have handled the outcome from `consumeUpgradeRedirect` so a
7
+ * page refresh does not replay it. `consumeUpgradeRedirect` never touches
8
+ * browser history, so clearing the param is your responsibility — this helper
9
+ * does it in one call, mirroring `clearSocialRedirectParams` and
10
+ * `clearDeviceRegistrationRedirectParams`. Unlike clearing the whole query
11
+ * string, it preserves any of your own parameters on the callback URL.
12
+ *
13
+ * This reads and rewrites `window.location`, so it can only run in the browser.
14
+ * Calling it during server-side rendering (no `window`) throws
15
+ * `UnavailableInServerSideError`. On React Native there is no browser address
16
+ * bar to clean — you own your navigation state — so a `.native` build throws
17
+ * instead.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const outcome = await consumeUpgradeRedirect({ url: window.location.href });
22
+ * if (outcome) {
23
+ * handleOutcome(outcome);
24
+ * clearUpgradeRedirectParams();
25
+ * }
26
+ * ```
27
+ * @returns Nothing. The current URL is rewritten in place via
28
+ * `window.history.replaceState`.
29
+ * @throws {UnavailableInServerSideError} When called during SSR (no `window`).
30
+ * @see consumeUpgradeRedirect
31
+ * @see startUpgradeRedirect
32
+ */
33
+ export declare const clearUpgradeRedirectParams: () => void;
34
+ //# sourceMappingURL=clearUpgradeRedirectParams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearUpgradeRedirectParams.d.ts","sourceRoot":"","sources":["../../src/clearUpgradeRedirectParams/clearUpgradeRedirectParams.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,0BAA0B,QAAO,IAU7C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { clearUpgradeRedirectParams } from './clearUpgradeRedirectParams';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clearUpgradeRedirectParams/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { BaseError } from '@dynamic-labs-sdk/client';
2
+ export declare class UpgradePopupBlockedError extends BaseError {
3
+ constructor();
4
+ }
5
+ //# sourceMappingURL=UpgradePopupBlockedError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpgradePopupBlockedError.d.ts","sourceRoot":"","sources":["../../src/errors/UpgradePopupBlockedError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,qBAAa,wBAAyB,SAAQ,SAAS;;CAWtD"}
@@ -0,0 +1,5 @@
1
+ import { BaseError } from '@dynamic-labs-sdk/client';
2
+ export declare class UpgradePopupClosedError extends BaseError {
3
+ constructor();
4
+ }
5
+ //# sourceMappingURL=UpgradePopupClosedError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpgradePopupClosedError.d.ts","sourceRoot":"","sources":["../../src/errors/UpgradePopupClosedError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,qBAAa,uBAAwB,SAAQ,SAAS;;CAUrD"}
@@ -3,8 +3,11 @@ export { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';
3
3
  export { hasWalletsRequiringUpgrade } from '../hasWalletsRequiringUpgrade';
4
4
  export { startUpgradeRedirect } from '../startUpgradeRedirect';
5
5
  export { consumeUpgradeRedirect, type ConsumeUpgradeRedirectParams, } from '../consumeUpgradeRedirect';
6
+ export { clearUpgradeRedirectParams } from '../clearUpgradeRedirectParams';
6
7
  export { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';
7
8
  export { openUpgradeIframe } from '../openUpgradeIframe';
8
9
  export type { UpgradeIframeSession } from '../openUpgradeIframe';
10
+ export { openUpgradePopup } from '../openUpgradePopup';
11
+ export type { UpgradePopupSession } from '../openUpgradePopup';
9
12
  export type { WalletUpgradeOutcome, WalletUpgradeStatus, } from '../upgradeAppContract';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,GAClC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,GAClC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
@@ -2,4 +2,5 @@ export { useWalletsRequiringUpgrade } from '../react/useWalletsRequiringUpgrade'
2
2
  export { useHasWalletsRequiringUpgrade } from '../react/useHasWalletsRequiringUpgrade';
3
3
  export { useUpgradeRedirectResult, type UseUpgradeRedirectResultParams, } from '../react/useUpgradeRedirectResult';
4
4
  export { useUpgradeIframe, type UseUpgradeIframeParams, type UseUpgradeIframeResult, } from '../react/useUpgradeIframe';
5
+ export { useUpgradePopup, type UseUpgradePopupParams, type UseUpgradePopupResult, } from '../react/useUpgradePopup';
5
6
  //# sourceMappingURL=react.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/exports/react.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EACL,wBAAwB,EACxB,KAAK,8BAA8B,GACpC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/exports/react.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EACL,wBAAwB,EACxB,KAAK,8BAA8B,GACpC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,0BAA0B,CAAC"}
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_subscribeToUpgradeCompletion = require('./subscribeToUpgradeCompletion-CjqiLYs5.cjs');
1
+ const require_openUpgradePopup = require('./openUpgradePopup-DuGh1T8k.cjs');
2
2
  let _dynamic_labs_sdk_assert_package_version = require("@dynamic-labs-sdk/assert-package-version");
3
3
  let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
4
4
  let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
@@ -24,7 +24,7 @@ let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
24
24
  * @see getWalletsRequiringUpgrade
25
25
  * @see startUpgradeRedirect
26
26
  */
27
- const hasWalletsRequiringUpgrade = (client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => require_subscribeToUpgradeCompletion.getWalletsRequiringUpgrade(client).length > 0;
27
+ const hasWalletsRequiringUpgrade = (client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => require_openUpgradePopup.getWalletsRequiringUpgrade(client).length > 0;
28
28
 
29
29
  //#endregion
30
30
  //#region src/startUpgradeRedirect/startUpgradeRedirect.ts
@@ -51,7 +51,7 @@ const hasWalletsRequiringUpgrade = (client = (0, _dynamic_labs_sdk_client.getDef
51
51
  * @see consumeUpgradeRedirect
52
52
  * @see buildUpgradeUrl
53
53
  */
54
- const startUpgradeRedirect = async (params = {}, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => (0, _dynamic_labs_sdk_client_core.getCore)(client).navigate(require_subscribeToUpgradeCompletion.buildUpgradeUrl(params, client));
54
+ const startUpgradeRedirect = async (params = {}, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => (0, _dynamic_labs_sdk_client_core.getCore)(client).navigate(require_openUpgradePopup.buildUpgradeUrl(params, client));
55
55
 
56
56
  //#endregion
57
57
  //#region src/errors/UpgradeIframeClosedError.ts
@@ -102,7 +102,7 @@ const UPGRADE_IFRAME_TITLE = "Dynamic embedded wallet upgrade";
102
102
  */
103
103
  const openUpgradeIframe = ({ container, redirectUrl, baseUrl }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
104
104
  const iframe = document.createElement("iframe");
105
- iframe.src = require_subscribeToUpgradeCompletion.buildUpgradeUrl({
105
+ iframe.src = require_openUpgradePopup.buildUpgradeUrl({
106
106
  baseUrl,
107
107
  redirectUrl
108
108
  }, client);
@@ -117,7 +117,7 @@ const openUpgradeIframe = ({ container, redirectUrl, baseUrl }, client = (0, _dy
117
117
  });
118
118
  completed.catch(() => void 0);
119
119
  let hasReceivedCompletion = false;
120
- const unsubscribe = require_subscribeToUpgradeCompletion.subscribeToUpgradeCompletion({
120
+ const unsubscribe = require_openUpgradePopup.subscribeToUpgradeCompletion({
121
121
  baseUrl,
122
122
  onComplete: (outcome) => resolveCompleted?.(outcome),
123
123
  onReceived: () => {
@@ -138,14 +138,16 @@ const openUpgradeIframe = ({ container, redirectUrl, baseUrl }, client = (0, _dy
138
138
 
139
139
  //#endregion
140
140
  //#region src/exports/index.ts
141
- (0, _dynamic_labs_sdk_assert_package_version.assertPackageVersion)(require_subscribeToUpgradeCompletion.name, require_subscribeToUpgradeCompletion.version);
141
+ (0, _dynamic_labs_sdk_assert_package_version.assertPackageVersion)(require_openUpgradePopup.name, require_openUpgradePopup.version);
142
142
 
143
143
  //#endregion
144
- exports.buildUpgradeUrl = require_subscribeToUpgradeCompletion.buildUpgradeUrl;
145
- exports.consumeUpgradeRedirect = require_subscribeToUpgradeCompletion.consumeUpgradeRedirect;
146
- exports.getWalletsRequiringUpgrade = require_subscribeToUpgradeCompletion.getWalletsRequiringUpgrade;
144
+ exports.buildUpgradeUrl = require_openUpgradePopup.buildUpgradeUrl;
145
+ exports.clearUpgradeRedirectParams = require_openUpgradePopup.clearUpgradeRedirectParams;
146
+ exports.consumeUpgradeRedirect = require_openUpgradePopup.consumeUpgradeRedirect;
147
+ exports.getWalletsRequiringUpgrade = require_openUpgradePopup.getWalletsRequiringUpgrade;
147
148
  exports.hasWalletsRequiringUpgrade = hasWalletsRequiringUpgrade;
148
149
  exports.openUpgradeIframe = openUpgradeIframe;
150
+ exports.openUpgradePopup = require_openUpgradePopup.openUpgradePopup;
149
151
  exports.startUpgradeRedirect = startUpgradeRedirect;
150
- exports.subscribeToUpgradeCompletion = require_subscribeToUpgradeCompletion.subscribeToUpgradeCompletion;
152
+ exports.subscribeToUpgradeCompletion = require_openUpgradePopup.subscribeToUpgradeCompletion;
151
153
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["getWalletsRequiringUpgrade","buildUpgradeUrl","BaseError","buildUpgradeUrl","resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined","rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined","subscribeToUpgradeCompletion","packageName","packageVersion"],"sources":["../src/hasWalletsRequiringUpgrade/hasWalletsRequiringUpgrade.ts","../src/startUpgradeRedirect/startUpgradeRedirect.ts","../src/errors/UpgradeIframeClosedError.ts","../src/openUpgradeIframe/openUpgradeIframe.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\n\n/**\n * Returns whether the current session has any legacy Dynamic embedded wallet\n * that requires an upgrade to Dynamic WaaS.\n *\n * A boolean convenience over {@link getWalletsRequiringUpgrade} for the common\n * case where you only need to decide whether to surface the upgrade flow (e.g.\n * show a banner or gate a wallet's actions) rather than act on the specific\n * accounts.\n *\n * @example\n * ```ts\n * if (hasWalletsRequiringUpgrade()) {\n * showUpgradeToWaasBanner();\n * }\n * ```\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns True when at least one wallet account requires an upgrade to Dynamic WaaS, false otherwise.\n * @see getWalletsRequiringUpgrade\n * @see startUpgradeRedirect\n */\nexport const hasWalletsRequiringUpgrade = (\n client = getDefaultClient()\n): boolean => getWalletsRequiringUpgrade(client).length > 0;\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\n\ntype StartUpgradeRedirectParams = {\n /**\n * Base URL of the hosted upgrade app. Defaults to the production upgrade app;\n * override it to target a local or preview build (e.g. during QA).\n */\n baseUrl?: string;\n /**\n * Absolute https URL the upgrade app returns to on completion. Defaults to\n * the current page (`window.location.href`), so the outcome can be picked up\n * by {@link consumeUpgradeRedirect} when the user lands back.\n */\n redirectUrl?: string;\n};\n\n/**\n * Starts the redirect upgrade path by navigating the top-level window to the\n * hosted upgrade app.\n *\n * Call this from an \"Upgrade\" button. The upgrade app runs full-page and, once\n * finished, returns the user to `redirectUrl` with the outcome encoded in the\n * URL — call {@link consumeUpgradeRedirect} on load to pick it up. The\n * environment id and return URL are derived from the client and current page,\n * so the common call is zero-arg.\n *\n * @example\n * ```ts\n * // on the \"Upgrade via redirect\" button\n * await startUpgradeRedirect();\n * ```\n * @param [params] - Options for the redirect.\n * @param [params.redirectUrl] - Absolute https return URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A promise that resolves once navigation has been initiated.\n * @see consumeUpgradeRedirect\n * @see buildUpgradeUrl\n */\nexport const startUpgradeRedirect = async (\n params: StartUpgradeRedirectParams = {},\n client = getDefaultClient()\n): Promise<void> =>\n getCore(client).navigate(buildUpgradeUrl(params, client));\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class UpgradeIframeClosedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'upgrade_iframe_closed_error',\n docsUrl: null,\n name: 'UpgradeIframeClosedError',\n shortMessage: 'Upgrade iframe was closed before the upgrade completed',\n });\n }\n}\n","/* eslint-disable no-restricted-globals */\n\nimport { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\nimport { UpgradeIframeClosedError } from '../errors/UpgradeIframeClosedError';\nimport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nimport type { WalletUpgradeOutcome } from '../upgradeAppContract';\nimport type {\n OpenUpgradeIframeParams,\n UpgradeIframeSession,\n} from './openUpgradeIframe.types';\n\nexport type { UpgradeIframeSession } from './openUpgradeIframe.types';\n\n// Permissions the upgrade app needs inside the iframe: clipboard writes plus\n// passkey (WebAuthn) get/create, which the embedded wallet upgrade relies on.\nconst UPGRADE_IFRAME_ALLOW =\n 'clipboard-write; publickey-credentials-get *; publickey-credentials-create *';\n\nconst UPGRADE_IFRAME_TITLE = 'Dynamic embedded wallet upgrade';\n\n/**\n * Runs the embedded upgrade path by mounting the hosted upgrade app in an\n * iframe inside a container you provide.\n *\n * The package renders no UI of its own: pass the element of your modal/sheet\n * and it appends the iframe, wires the origin-checked completion handshake, and\n * refreshes the session on success. `completed` resolves with the outcome once\n * the app reports back; call `close()` when the user dismisses the surface (or\n * after completion) to remove the iframe and detach the listener. Closing\n * before completion rejects `completed` with {@link UpgradeIframeClosedError}\n * so awaiters don't hang — wrap `await session.completed` in try/catch if you\n * allow early dismissal. For React Native or custom mounts, use\n * {@link subscribeToUpgradeCompletion} with {@link buildUpgradeUrl} instead.\n *\n * @example\n * ```ts\n * const session = openUpgradeIframe({ container: sheetBodyEl });\n * const { status } = await session.completed;\n * session.close();\n * ```\n * @param params - Iframe options.\n * @param params.container - Element the upgrade iframe is appended into.\n * @param [params.redirectUrl] - Absolute https completion URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A session handle exposing the `iframe`, a `close` function, and the `completed` promise.\n * @see subscribeToUpgradeCompletion\n * @see buildUpgradeUrl\n */\nexport const openUpgradeIframe = (\n { container, redirectUrl, baseUrl }: OpenUpgradeIframeParams,\n client = getDefaultClient()\n): UpgradeIframeSession => {\n const iframe = document.createElement('iframe');\n iframe.src = buildUpgradeUrl({ baseUrl, redirectUrl }, client);\n iframe.title = UPGRADE_IFRAME_TITLE;\n iframe.setAttribute('allow', UPGRADE_IFRAME_ALLOW);\n\n container.appendChild(iframe);\n\n // Executor runs synchronously, so both settlers are assigned before the\n // subscription below (or `close`) can ever fire.\n let resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined;\n let rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined;\n const completed = new Promise<WalletUpgradeOutcome>((resolve, reject) => {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n // Callers may use `close()` purely for teardown and never await `completed`.\n // Attach a no-op catch so an early-close rejection is treated as handled\n // globally (no unhandled-rejection noise); a caller that does await\n // `completed` still receives the rejection in its own context.\n completed.catch(() => undefined);\n\n // Set the instant a valid completion message arrives — before the async\n // session refresh resolves `completed` via `onComplete`. `close()` checks\n // this so dismissing the surface during that refresh window does not reject a\n // promise for an upgrade that already succeeded.\n let hasReceivedCompletion = false;\n\n const unsubscribe = subscribeToUpgradeCompletion(\n {\n baseUrl,\n onComplete: (outcome) => resolveCompleted?.(outcome),\n onReceived: () => {\n hasReceivedCompletion = true;\n },\n },\n client\n );\n\n const close = () => {\n unsubscribe();\n iframe.remove();\n // Reject `completed` only as a genuine cancellation — i.e. no completion\n // has been received yet — so anything awaiting it doesn't hang forever. If\n // a completion already arrived, `onComplete` (after the refresh) resolves\n // `completed` with the real outcome, so we must not reject here.\n if (!hasReceivedCompletion) {\n rejectCompleted?.(new UpgradeIframeClosedError());\n }\n };\n\n return { close, completed, iframe };\n};\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n name as packageName,\n version as packageVersion,\n} from '../../package.json';\n\nassertPackageVersion(packageName, packageVersion);\n\nexport { buildUpgradeUrl } from '../buildUpgradeUrl';\nexport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\nexport { hasWalletsRequiringUpgrade } from '../hasWalletsRequiringUpgrade';\nexport { startUpgradeRedirect } from '../startUpgradeRedirect';\nexport {\n consumeUpgradeRedirect,\n type ConsumeUpgradeRedirectParams,\n} from '../consumeUpgradeRedirect';\nexport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nexport { openUpgradeIframe } from '../openUpgradeIframe';\nexport type { UpgradeIframeSession } from '../openUpgradeIframe';\nexport type {\n WalletUpgradeOutcome,\n WalletUpgradeStatus,\n} from '../upgradeAppContract';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,8BACX,yDAA2B,KACfA,gEAA2B,OAAO,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgB1D,MAAa,uBAAuB,OAClC,SAAqC,EAAE,EACvC,yDAA2B,gDAEnB,OAAO,CAAC,SAASC,qDAAgB,QAAQ,OAAO,CAAC;;;;AC5C3D,IAAa,2BAAb,cAA8CC,mCAAU;CACtD,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cAAc;GACf,CAAC;;;;;;ACON,MAAM,uBACJ;AAEF,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+B7B,MAAa,qBACX,EAAE,WAAW,aAAa,WAC1B,yDAA2B,KACF;CACzB,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,MAAMC,qDAAgB;EAAE;EAAS;EAAa,EAAE,OAAO;AAC9D,QAAO,QAAQ;AACf,QAAO,aAAa,SAAS,qBAAqB;AAElD,WAAU,YAAY,OAAO;CAI7B,IAAIC;CACJ,IAAIC;CACJ,MAAM,YAAY,IAAI,SAA+B,SAAS,WAAW;AACvE,qBAAmB;AACnB,oBAAkB;GAClB;AAMF,WAAU,YAAY,OAAU;CAMhC,IAAI,wBAAwB;CAE5B,MAAM,cAAcC,kEAClB;EACE;EACA,aAAa,YAAY,mBAAmB,QAAQ;EACpD,kBAAkB;AAChB,2BAAwB;;EAE3B,EACD,OACD;CAED,MAAM,cAAc;AAClB,eAAa;AACb,SAAO,QAAQ;AAKf,MAAI,CAAC,sBACH,mBAAkB,IAAI,0BAA0B,CAAC;;AAIrD,QAAO;EAAE;EAAO;EAAW;EAAQ;;;;;mECnGhBC,2CAAaC,6CAAe"}
1
+ {"version":3,"file":"index.cjs","names":["getWalletsRequiringUpgrade","buildUpgradeUrl","BaseError","buildUpgradeUrl","resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined","rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined","subscribeToUpgradeCompletion","packageName","packageVersion"],"sources":["../src/hasWalletsRequiringUpgrade/hasWalletsRequiringUpgrade.ts","../src/startUpgradeRedirect/startUpgradeRedirect.ts","../src/errors/UpgradeIframeClosedError.ts","../src/openUpgradeIframe/openUpgradeIframe.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\n\n/**\n * Returns whether the current session has any legacy Dynamic embedded wallet\n * that requires an upgrade to Dynamic WaaS.\n *\n * A boolean convenience over {@link getWalletsRequiringUpgrade} for the common\n * case where you only need to decide whether to surface the upgrade flow (e.g.\n * show a banner or gate a wallet's actions) rather than act on the specific\n * accounts.\n *\n * @example\n * ```ts\n * if (hasWalletsRequiringUpgrade()) {\n * showUpgradeToWaasBanner();\n * }\n * ```\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns True when at least one wallet account requires an upgrade to Dynamic WaaS, false otherwise.\n * @see getWalletsRequiringUpgrade\n * @see startUpgradeRedirect\n */\nexport const hasWalletsRequiringUpgrade = (\n client = getDefaultClient()\n): boolean => getWalletsRequiringUpgrade(client).length > 0;\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\n\ntype StartUpgradeRedirectParams = {\n /**\n * Base URL of the hosted upgrade app. Defaults to the production upgrade app;\n * override it to target a local or preview build (e.g. during QA).\n */\n baseUrl?: string;\n /**\n * Absolute https URL the upgrade app returns to on completion. Defaults to\n * the current page (`window.location.href`), so the outcome can be picked up\n * by {@link consumeUpgradeRedirect} when the user lands back.\n */\n redirectUrl?: string;\n};\n\n/**\n * Starts the redirect upgrade path by navigating the top-level window to the\n * hosted upgrade app.\n *\n * Call this from an \"Upgrade\" button. The upgrade app runs full-page and, once\n * finished, returns the user to `redirectUrl` with the outcome encoded in the\n * URL — call {@link consumeUpgradeRedirect} on load to pick it up. The\n * environment id and return URL are derived from the client and current page,\n * so the common call is zero-arg.\n *\n * @example\n * ```ts\n * // on the \"Upgrade via redirect\" button\n * await startUpgradeRedirect();\n * ```\n * @param [params] - Options for the redirect.\n * @param [params.redirectUrl] - Absolute https return URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A promise that resolves once navigation has been initiated.\n * @see consumeUpgradeRedirect\n * @see buildUpgradeUrl\n */\nexport const startUpgradeRedirect = async (\n params: StartUpgradeRedirectParams = {},\n client = getDefaultClient()\n): Promise<void> =>\n getCore(client).navigate(buildUpgradeUrl(params, client));\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class UpgradeIframeClosedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'upgrade_iframe_closed_error',\n docsUrl: null,\n name: 'UpgradeIframeClosedError',\n shortMessage: 'Upgrade iframe was closed before the upgrade completed',\n });\n }\n}\n","/* eslint-disable no-restricted-globals */\n\nimport { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\nimport { UpgradeIframeClosedError } from '../errors/UpgradeIframeClosedError';\nimport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nimport type { WalletUpgradeOutcome } from '../upgradeAppContract';\nimport type {\n OpenUpgradeIframeParams,\n UpgradeIframeSession,\n} from './openUpgradeIframe.types';\n\nexport type { UpgradeIframeSession } from './openUpgradeIframe.types';\n\n// Permissions the upgrade app needs inside the iframe: clipboard writes plus\n// passkey (WebAuthn) get/create, which the embedded wallet upgrade relies on.\nconst UPGRADE_IFRAME_ALLOW =\n 'clipboard-write; publickey-credentials-get *; publickey-credentials-create *';\n\nconst UPGRADE_IFRAME_TITLE = 'Dynamic embedded wallet upgrade';\n\n/**\n * Runs the embedded upgrade path by mounting the hosted upgrade app in an\n * iframe inside a container you provide.\n *\n * The package renders no UI of its own: pass the element of your modal/sheet\n * and it appends the iframe, wires the origin-checked completion handshake, and\n * refreshes the session on success. `completed` resolves with the outcome once\n * the app reports back; call `close()` when the user dismisses the surface (or\n * after completion) to remove the iframe and detach the listener. Closing\n * before completion rejects `completed` with {@link UpgradeIframeClosedError}\n * so awaiters don't hang — wrap `await session.completed` in try/catch if you\n * allow early dismissal. For React Native or custom mounts, use\n * {@link subscribeToUpgradeCompletion} with {@link buildUpgradeUrl} instead.\n *\n * @example\n * ```ts\n * const session = openUpgradeIframe({ container: sheetBodyEl });\n * const { status } = await session.completed;\n * session.close();\n * ```\n * @param params - Iframe options.\n * @param params.container - Element the upgrade iframe is appended into.\n * @param [params.redirectUrl] - Absolute https completion URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A session handle exposing the `iframe`, a `close` function, and the `completed` promise.\n * @see subscribeToUpgradeCompletion\n * @see buildUpgradeUrl\n */\nexport const openUpgradeIframe = (\n { container, redirectUrl, baseUrl }: OpenUpgradeIframeParams,\n client = getDefaultClient()\n): UpgradeIframeSession => {\n const iframe = document.createElement('iframe');\n iframe.src = buildUpgradeUrl({ baseUrl, redirectUrl }, client);\n iframe.title = UPGRADE_IFRAME_TITLE;\n iframe.setAttribute('allow', UPGRADE_IFRAME_ALLOW);\n\n container.appendChild(iframe);\n\n // Executor runs synchronously, so both settlers are assigned before the\n // subscription below (or `close`) can ever fire.\n let resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined;\n let rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined;\n const completed = new Promise<WalletUpgradeOutcome>((resolve, reject) => {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n // Callers may use `close()` purely for teardown and never await `completed`.\n // Attach a no-op catch so an early-close rejection is treated as handled\n // globally (no unhandled-rejection noise); a caller that does await\n // `completed` still receives the rejection in its own context.\n completed.catch(() => undefined);\n\n // Set the instant a valid completion message arrives — before the async\n // session refresh resolves `completed` via `onComplete`. `close()` checks\n // this so dismissing the surface during that refresh window does not reject a\n // promise for an upgrade that already succeeded.\n let hasReceivedCompletion = false;\n\n const unsubscribe = subscribeToUpgradeCompletion(\n {\n baseUrl,\n onComplete: (outcome) => resolveCompleted?.(outcome),\n onReceived: () => {\n hasReceivedCompletion = true;\n },\n },\n client\n );\n\n const close = () => {\n unsubscribe();\n iframe.remove();\n // Reject `completed` only as a genuine cancellation — i.e. no completion\n // has been received yet — so anything awaiting it doesn't hang forever. If\n // a completion already arrived, `onComplete` (after the refresh) resolves\n // `completed` with the real outcome, so we must not reject here.\n if (!hasReceivedCompletion) {\n rejectCompleted?.(new UpgradeIframeClosedError());\n }\n };\n\n return { close, completed, iframe };\n};\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n name as packageName,\n version as packageVersion,\n} from '../../package.json';\n\nassertPackageVersion(packageName, packageVersion);\n\nexport { buildUpgradeUrl } from '../buildUpgradeUrl';\nexport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\nexport { hasWalletsRequiringUpgrade } from '../hasWalletsRequiringUpgrade';\nexport { startUpgradeRedirect } from '../startUpgradeRedirect';\nexport {\n consumeUpgradeRedirect,\n type ConsumeUpgradeRedirectParams,\n} from '../consumeUpgradeRedirect';\nexport { clearUpgradeRedirectParams } from '../clearUpgradeRedirectParams';\nexport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nexport { openUpgradeIframe } from '../openUpgradeIframe';\nexport type { UpgradeIframeSession } from '../openUpgradeIframe';\nexport { openUpgradePopup } from '../openUpgradePopup';\nexport type { UpgradePopupSession } from '../openUpgradePopup';\nexport type {\n WalletUpgradeOutcome,\n WalletUpgradeStatus,\n} from '../upgradeAppContract';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,8BACX,yDAA2B,KACfA,oDAA2B,OAAO,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgB1D,MAAa,uBAAuB,OAClC,SAAqC,EAAE,EACvC,yDAA2B,gDAEnB,OAAO,CAAC,SAASC,yCAAgB,QAAQ,OAAO,CAAC;;;;AC5C3D,IAAa,2BAAb,cAA8CC,mCAAU;CACtD,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cAAc;GACf,CAAC;;;;;;ACON,MAAM,uBACJ;AAEF,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+B7B,MAAa,qBACX,EAAE,WAAW,aAAa,WAC1B,yDAA2B,KACF;CACzB,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,MAAMC,yCAAgB;EAAE;EAAS;EAAa,EAAE,OAAO;AAC9D,QAAO,QAAQ;AACf,QAAO,aAAa,SAAS,qBAAqB;AAElD,WAAU,YAAY,OAAO;CAI7B,IAAIC;CACJ,IAAIC;CACJ,MAAM,YAAY,IAAI,SAA+B,SAAS,WAAW;AACvE,qBAAmB;AACnB,oBAAkB;GAClB;AAMF,WAAU,YAAY,OAAU;CAMhC,IAAI,wBAAwB;CAE5B,MAAM,cAAcC,sDAClB;EACE;EACA,aAAa,YAAY,mBAAmB,QAAQ;EACpD,kBAAkB;AAChB,2BAAwB;;EAE3B,EACD,OACD;CAED,MAAM,cAAc;AAClB,eAAa;AACb,SAAO,QAAQ;AAKf,MAAI,CAAC,sBACH,mBAAkB,IAAI,0BAA0B,CAAC;;AAIrD,QAAO;EAAE;EAAO;EAAW;EAAQ;;;;;mECnGhBC,+BAAaC,iCAAe"}
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { i as buildUpgradeUrl, n as consumeUpgradeRedirect, o as name, r as getWalletsRequiringUpgrade, s as version, t as subscribeToUpgradeCompletion } from "./subscribeToUpgradeCompletion-BuoizMF2.esm.js";
1
+ import { a as getWalletsRequiringUpgrade, c as version, i as consumeUpgradeRedirect, n as subscribeToUpgradeCompletion, o as buildUpgradeUrl, r as clearUpgradeRedirectParams, s as name, t as openUpgradePopup } from "./openUpgradePopup-DNe06for.esm.js";
2
2
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
3
3
  import { BaseError, getDefaultClient } from "@dynamic-labs-sdk/client";
4
4
  import { getCore } from "@dynamic-labs-sdk/client/core";
@@ -141,5 +141,5 @@ const openUpgradeIframe = ({ container, redirectUrl, baseUrl }, client = getDefa
141
141
  assertPackageVersion(name, version);
142
142
 
143
143
  //#endregion
144
- export { buildUpgradeUrl, consumeUpgradeRedirect, getWalletsRequiringUpgrade, hasWalletsRequiringUpgrade, openUpgradeIframe, startUpgradeRedirect, subscribeToUpgradeCompletion };
144
+ export { buildUpgradeUrl, clearUpgradeRedirectParams, consumeUpgradeRedirect, getWalletsRequiringUpgrade, hasWalletsRequiringUpgrade, openUpgradeIframe, openUpgradePopup, startUpgradeRedirect, subscribeToUpgradeCompletion };
145
145
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","names":["resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined","rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined","packageName","packageVersion"],"sources":["../src/hasWalletsRequiringUpgrade/hasWalletsRequiringUpgrade.ts","../src/startUpgradeRedirect/startUpgradeRedirect.ts","../src/errors/UpgradeIframeClosedError.ts","../src/openUpgradeIframe/openUpgradeIframe.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\n\n/**\n * Returns whether the current session has any legacy Dynamic embedded wallet\n * that requires an upgrade to Dynamic WaaS.\n *\n * A boolean convenience over {@link getWalletsRequiringUpgrade} for the common\n * case where you only need to decide whether to surface the upgrade flow (e.g.\n * show a banner or gate a wallet's actions) rather than act on the specific\n * accounts.\n *\n * @example\n * ```ts\n * if (hasWalletsRequiringUpgrade()) {\n * showUpgradeToWaasBanner();\n * }\n * ```\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns True when at least one wallet account requires an upgrade to Dynamic WaaS, false otherwise.\n * @see getWalletsRequiringUpgrade\n * @see startUpgradeRedirect\n */\nexport const hasWalletsRequiringUpgrade = (\n client = getDefaultClient()\n): boolean => getWalletsRequiringUpgrade(client).length > 0;\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\n\ntype StartUpgradeRedirectParams = {\n /**\n * Base URL of the hosted upgrade app. Defaults to the production upgrade app;\n * override it to target a local or preview build (e.g. during QA).\n */\n baseUrl?: string;\n /**\n * Absolute https URL the upgrade app returns to on completion. Defaults to\n * the current page (`window.location.href`), so the outcome can be picked up\n * by {@link consumeUpgradeRedirect} when the user lands back.\n */\n redirectUrl?: string;\n};\n\n/**\n * Starts the redirect upgrade path by navigating the top-level window to the\n * hosted upgrade app.\n *\n * Call this from an \"Upgrade\" button. The upgrade app runs full-page and, once\n * finished, returns the user to `redirectUrl` with the outcome encoded in the\n * URL — call {@link consumeUpgradeRedirect} on load to pick it up. The\n * environment id and return URL are derived from the client and current page,\n * so the common call is zero-arg.\n *\n * @example\n * ```ts\n * // on the \"Upgrade via redirect\" button\n * await startUpgradeRedirect();\n * ```\n * @param [params] - Options for the redirect.\n * @param [params.redirectUrl] - Absolute https return URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A promise that resolves once navigation has been initiated.\n * @see consumeUpgradeRedirect\n * @see buildUpgradeUrl\n */\nexport const startUpgradeRedirect = async (\n params: StartUpgradeRedirectParams = {},\n client = getDefaultClient()\n): Promise<void> =>\n getCore(client).navigate(buildUpgradeUrl(params, client));\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class UpgradeIframeClosedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'upgrade_iframe_closed_error',\n docsUrl: null,\n name: 'UpgradeIframeClosedError',\n shortMessage: 'Upgrade iframe was closed before the upgrade completed',\n });\n }\n}\n","/* eslint-disable no-restricted-globals */\n\nimport { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\nimport { UpgradeIframeClosedError } from '../errors/UpgradeIframeClosedError';\nimport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nimport type { WalletUpgradeOutcome } from '../upgradeAppContract';\nimport type {\n OpenUpgradeIframeParams,\n UpgradeIframeSession,\n} from './openUpgradeIframe.types';\n\nexport type { UpgradeIframeSession } from './openUpgradeIframe.types';\n\n// Permissions the upgrade app needs inside the iframe: clipboard writes plus\n// passkey (WebAuthn) get/create, which the embedded wallet upgrade relies on.\nconst UPGRADE_IFRAME_ALLOW =\n 'clipboard-write; publickey-credentials-get *; publickey-credentials-create *';\n\nconst UPGRADE_IFRAME_TITLE = 'Dynamic embedded wallet upgrade';\n\n/**\n * Runs the embedded upgrade path by mounting the hosted upgrade app in an\n * iframe inside a container you provide.\n *\n * The package renders no UI of its own: pass the element of your modal/sheet\n * and it appends the iframe, wires the origin-checked completion handshake, and\n * refreshes the session on success. `completed` resolves with the outcome once\n * the app reports back; call `close()` when the user dismisses the surface (or\n * after completion) to remove the iframe and detach the listener. Closing\n * before completion rejects `completed` with {@link UpgradeIframeClosedError}\n * so awaiters don't hang — wrap `await session.completed` in try/catch if you\n * allow early dismissal. For React Native or custom mounts, use\n * {@link subscribeToUpgradeCompletion} with {@link buildUpgradeUrl} instead.\n *\n * @example\n * ```ts\n * const session = openUpgradeIframe({ container: sheetBodyEl });\n * const { status } = await session.completed;\n * session.close();\n * ```\n * @param params - Iframe options.\n * @param params.container - Element the upgrade iframe is appended into.\n * @param [params.redirectUrl] - Absolute https completion URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A session handle exposing the `iframe`, a `close` function, and the `completed` promise.\n * @see subscribeToUpgradeCompletion\n * @see buildUpgradeUrl\n */\nexport const openUpgradeIframe = (\n { container, redirectUrl, baseUrl }: OpenUpgradeIframeParams,\n client = getDefaultClient()\n): UpgradeIframeSession => {\n const iframe = document.createElement('iframe');\n iframe.src = buildUpgradeUrl({ baseUrl, redirectUrl }, client);\n iframe.title = UPGRADE_IFRAME_TITLE;\n iframe.setAttribute('allow', UPGRADE_IFRAME_ALLOW);\n\n container.appendChild(iframe);\n\n // Executor runs synchronously, so both settlers are assigned before the\n // subscription below (or `close`) can ever fire.\n let resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined;\n let rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined;\n const completed = new Promise<WalletUpgradeOutcome>((resolve, reject) => {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n // Callers may use `close()` purely for teardown and never await `completed`.\n // Attach a no-op catch so an early-close rejection is treated as handled\n // globally (no unhandled-rejection noise); a caller that does await\n // `completed` still receives the rejection in its own context.\n completed.catch(() => undefined);\n\n // Set the instant a valid completion message arrives — before the async\n // session refresh resolves `completed` via `onComplete`. `close()` checks\n // this so dismissing the surface during that refresh window does not reject a\n // promise for an upgrade that already succeeded.\n let hasReceivedCompletion = false;\n\n const unsubscribe = subscribeToUpgradeCompletion(\n {\n baseUrl,\n onComplete: (outcome) => resolveCompleted?.(outcome),\n onReceived: () => {\n hasReceivedCompletion = true;\n },\n },\n client\n );\n\n const close = () => {\n unsubscribe();\n iframe.remove();\n // Reject `completed` only as a genuine cancellation — i.e. no completion\n // has been received yet — so anything awaiting it doesn't hang forever. If\n // a completion already arrived, `onComplete` (after the refresh) resolves\n // `completed` with the real outcome, so we must not reject here.\n if (!hasReceivedCompletion) {\n rejectCompleted?.(new UpgradeIframeClosedError());\n }\n };\n\n return { close, completed, iframe };\n};\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n name as packageName,\n version as packageVersion,\n} from '../../package.json';\n\nassertPackageVersion(packageName, packageVersion);\n\nexport { buildUpgradeUrl } from '../buildUpgradeUrl';\nexport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\nexport { hasWalletsRequiringUpgrade } from '../hasWalletsRequiringUpgrade';\nexport { startUpgradeRedirect } from '../startUpgradeRedirect';\nexport {\n consumeUpgradeRedirect,\n type ConsumeUpgradeRedirectParams,\n} from '../consumeUpgradeRedirect';\nexport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nexport { openUpgradeIframe } from '../openUpgradeIframe';\nexport type { UpgradeIframeSession } from '../openUpgradeIframe';\nexport type {\n WalletUpgradeOutcome,\n WalletUpgradeStatus,\n} from '../upgradeAppContract';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,8BACX,SAAS,kBAAkB,KACf,2BAA2B,OAAO,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgB1D,MAAa,uBAAuB,OAClC,SAAqC,EAAE,EACvC,SAAS,kBAAkB,KAE3B,QAAQ,OAAO,CAAC,SAAS,gBAAgB,QAAQ,OAAO,CAAC;;;;AC5C3D,IAAa,2BAAb,cAA8C,UAAU;CACtD,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cAAc;GACf,CAAC;;;;;;ACON,MAAM,uBACJ;AAEF,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+B7B,MAAa,qBACX,EAAE,WAAW,aAAa,WAC1B,SAAS,kBAAkB,KACF;CACzB,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,MAAM,gBAAgB;EAAE;EAAS;EAAa,EAAE,OAAO;AAC9D,QAAO,QAAQ;AACf,QAAO,aAAa,SAAS,qBAAqB;AAElD,WAAU,YAAY,OAAO;CAI7B,IAAIA;CACJ,IAAIC;CACJ,MAAM,YAAY,IAAI,SAA+B,SAAS,WAAW;AACvE,qBAAmB;AACnB,oBAAkB;GAClB;AAMF,WAAU,YAAY,OAAU;CAMhC,IAAI,wBAAwB;CAE5B,MAAM,cAAc,6BAClB;EACE;EACA,aAAa,YAAY,mBAAmB,QAAQ;EACpD,kBAAkB;AAChB,2BAAwB;;EAE3B,EACD,OACD;CAED,MAAM,cAAc;AAClB,eAAa;AACb,SAAO,QAAQ;AAKf,MAAI,CAAC,sBACH,mBAAkB,IAAI,0BAA0B,CAAC;;AAIrD,QAAO;EAAE;EAAO;EAAW;EAAQ;;;;;ACnGrC,qBAAqBC,MAAaC,QAAe"}
1
+ {"version":3,"file":"index.esm.js","names":["resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined","rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined","packageName","packageVersion"],"sources":["../src/hasWalletsRequiringUpgrade/hasWalletsRequiringUpgrade.ts","../src/startUpgradeRedirect/startUpgradeRedirect.ts","../src/errors/UpgradeIframeClosedError.ts","../src/openUpgradeIframe/openUpgradeIframe.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\n\n/**\n * Returns whether the current session has any legacy Dynamic embedded wallet\n * that requires an upgrade to Dynamic WaaS.\n *\n * A boolean convenience over {@link getWalletsRequiringUpgrade} for the common\n * case where you only need to decide whether to surface the upgrade flow (e.g.\n * show a banner or gate a wallet's actions) rather than act on the specific\n * accounts.\n *\n * @example\n * ```ts\n * if (hasWalletsRequiringUpgrade()) {\n * showUpgradeToWaasBanner();\n * }\n * ```\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns True when at least one wallet account requires an upgrade to Dynamic WaaS, false otherwise.\n * @see getWalletsRequiringUpgrade\n * @see startUpgradeRedirect\n */\nexport const hasWalletsRequiringUpgrade = (\n client = getDefaultClient()\n): boolean => getWalletsRequiringUpgrade(client).length > 0;\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\n\ntype StartUpgradeRedirectParams = {\n /**\n * Base URL of the hosted upgrade app. Defaults to the production upgrade app;\n * override it to target a local or preview build (e.g. during QA).\n */\n baseUrl?: string;\n /**\n * Absolute https URL the upgrade app returns to on completion. Defaults to\n * the current page (`window.location.href`), so the outcome can be picked up\n * by {@link consumeUpgradeRedirect} when the user lands back.\n */\n redirectUrl?: string;\n};\n\n/**\n * Starts the redirect upgrade path by navigating the top-level window to the\n * hosted upgrade app.\n *\n * Call this from an \"Upgrade\" button. The upgrade app runs full-page and, once\n * finished, returns the user to `redirectUrl` with the outcome encoded in the\n * URL — call {@link consumeUpgradeRedirect} on load to pick it up. The\n * environment id and return URL are derived from the client and current page,\n * so the common call is zero-arg.\n *\n * @example\n * ```ts\n * // on the \"Upgrade via redirect\" button\n * await startUpgradeRedirect();\n * ```\n * @param [params] - Options for the redirect.\n * @param [params.redirectUrl] - Absolute https return URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A promise that resolves once navigation has been initiated.\n * @see consumeUpgradeRedirect\n * @see buildUpgradeUrl\n */\nexport const startUpgradeRedirect = async (\n params: StartUpgradeRedirectParams = {},\n client = getDefaultClient()\n): Promise<void> =>\n getCore(client).navigate(buildUpgradeUrl(params, client));\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class UpgradeIframeClosedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'upgrade_iframe_closed_error',\n docsUrl: null,\n name: 'UpgradeIframeClosedError',\n shortMessage: 'Upgrade iframe was closed before the upgrade completed',\n });\n }\n}\n","/* eslint-disable no-restricted-globals */\n\nimport { getDefaultClient } from '@dynamic-labs-sdk/client';\n\nimport { buildUpgradeUrl } from '../buildUpgradeUrl';\nimport { UpgradeIframeClosedError } from '../errors/UpgradeIframeClosedError';\nimport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nimport type { WalletUpgradeOutcome } from '../upgradeAppContract';\nimport type {\n OpenUpgradeIframeParams,\n UpgradeIframeSession,\n} from './openUpgradeIframe.types';\n\nexport type { UpgradeIframeSession } from './openUpgradeIframe.types';\n\n// Permissions the upgrade app needs inside the iframe: clipboard writes plus\n// passkey (WebAuthn) get/create, which the embedded wallet upgrade relies on.\nconst UPGRADE_IFRAME_ALLOW =\n 'clipboard-write; publickey-credentials-get *; publickey-credentials-create *';\n\nconst UPGRADE_IFRAME_TITLE = 'Dynamic embedded wallet upgrade';\n\n/**\n * Runs the embedded upgrade path by mounting the hosted upgrade app in an\n * iframe inside a container you provide.\n *\n * The package renders no UI of its own: pass the element of your modal/sheet\n * and it appends the iframe, wires the origin-checked completion handshake, and\n * refreshes the session on success. `completed` resolves with the outcome once\n * the app reports back; call `close()` when the user dismisses the surface (or\n * after completion) to remove the iframe and detach the listener. Closing\n * before completion rejects `completed` with {@link UpgradeIframeClosedError}\n * so awaiters don't hang — wrap `await session.completed` in try/catch if you\n * allow early dismissal. For React Native or custom mounts, use\n * {@link subscribeToUpgradeCompletion} with {@link buildUpgradeUrl} instead.\n *\n * @example\n * ```ts\n * const session = openUpgradeIframe({ container: sheetBodyEl });\n * const { status } = await session.completed;\n * session.close();\n * ```\n * @param params - Iframe options.\n * @param params.container - Element the upgrade iframe is appended into.\n * @param [params.redirectUrl] - Absolute https completion URL; defaults to `window.location.href`.\n * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A session handle exposing the `iframe`, a `close` function, and the `completed` promise.\n * @see subscribeToUpgradeCompletion\n * @see buildUpgradeUrl\n */\nexport const openUpgradeIframe = (\n { container, redirectUrl, baseUrl }: OpenUpgradeIframeParams,\n client = getDefaultClient()\n): UpgradeIframeSession => {\n const iframe = document.createElement('iframe');\n iframe.src = buildUpgradeUrl({ baseUrl, redirectUrl }, client);\n iframe.title = UPGRADE_IFRAME_TITLE;\n iframe.setAttribute('allow', UPGRADE_IFRAME_ALLOW);\n\n container.appendChild(iframe);\n\n // Executor runs synchronously, so both settlers are assigned before the\n // subscription below (or `close`) can ever fire.\n let resolveCompleted: ((outcome: WalletUpgradeOutcome) => void) | undefined;\n let rejectCompleted: ((reason: UpgradeIframeClosedError) => void) | undefined;\n const completed = new Promise<WalletUpgradeOutcome>((resolve, reject) => {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n // Callers may use `close()` purely for teardown and never await `completed`.\n // Attach a no-op catch so an early-close rejection is treated as handled\n // globally (no unhandled-rejection noise); a caller that does await\n // `completed` still receives the rejection in its own context.\n completed.catch(() => undefined);\n\n // Set the instant a valid completion message arrives — before the async\n // session refresh resolves `completed` via `onComplete`. `close()` checks\n // this so dismissing the surface during that refresh window does not reject a\n // promise for an upgrade that already succeeded.\n let hasReceivedCompletion = false;\n\n const unsubscribe = subscribeToUpgradeCompletion(\n {\n baseUrl,\n onComplete: (outcome) => resolveCompleted?.(outcome),\n onReceived: () => {\n hasReceivedCompletion = true;\n },\n },\n client\n );\n\n const close = () => {\n unsubscribe();\n iframe.remove();\n // Reject `completed` only as a genuine cancellation — i.e. no completion\n // has been received yet — so anything awaiting it doesn't hang forever. If\n // a completion already arrived, `onComplete` (after the refresh) resolves\n // `completed` with the real outcome, so we must not reject here.\n if (!hasReceivedCompletion) {\n rejectCompleted?.(new UpgradeIframeClosedError());\n }\n };\n\n return { close, completed, iframe };\n};\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n name as packageName,\n version as packageVersion,\n} from '../../package.json';\n\nassertPackageVersion(packageName, packageVersion);\n\nexport { buildUpgradeUrl } from '../buildUpgradeUrl';\nexport { getWalletsRequiringUpgrade } from '../getWalletsRequiringUpgrade';\nexport { hasWalletsRequiringUpgrade } from '../hasWalletsRequiringUpgrade';\nexport { startUpgradeRedirect } from '../startUpgradeRedirect';\nexport {\n consumeUpgradeRedirect,\n type ConsumeUpgradeRedirectParams,\n} from '../consumeUpgradeRedirect';\nexport { clearUpgradeRedirectParams } from '../clearUpgradeRedirectParams';\nexport { subscribeToUpgradeCompletion } from '../subscribeToUpgradeCompletion';\nexport { openUpgradeIframe } from '../openUpgradeIframe';\nexport type { UpgradeIframeSession } from '../openUpgradeIframe';\nexport { openUpgradePopup } from '../openUpgradePopup';\nexport type { UpgradePopupSession } from '../openUpgradePopup';\nexport type {\n WalletUpgradeOutcome,\n WalletUpgradeStatus,\n} from '../upgradeAppContract';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,8BACX,SAAS,kBAAkB,KACf,2BAA2B,OAAO,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgB1D,MAAa,uBAAuB,OAClC,SAAqC,EAAE,EACvC,SAAS,kBAAkB,KAE3B,QAAQ,OAAO,CAAC,SAAS,gBAAgB,QAAQ,OAAO,CAAC;;;;AC5C3D,IAAa,2BAAb,cAA8C,UAAU;CACtD,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cAAc;GACf,CAAC;;;;;;ACON,MAAM,uBACJ;AAEF,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+B7B,MAAa,qBACX,EAAE,WAAW,aAAa,WAC1B,SAAS,kBAAkB,KACF;CACzB,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,MAAM,gBAAgB;EAAE;EAAS;EAAa,EAAE,OAAO;AAC9D,QAAO,QAAQ;AACf,QAAO,aAAa,SAAS,qBAAqB;AAElD,WAAU,YAAY,OAAO;CAI7B,IAAIA;CACJ,IAAIC;CACJ,MAAM,YAAY,IAAI,SAA+B,SAAS,WAAW;AACvE,qBAAmB;AACnB,oBAAkB;GAClB;AAMF,WAAU,YAAY,OAAU;CAMhC,IAAI,wBAAwB;CAE5B,MAAM,cAAc,6BAClB;EACE;EACA,aAAa,YAAY,mBAAmB,QAAQ;EACpD,kBAAkB;AAChB,2BAAwB;;EAE3B,EACD,OACD;CAED,MAAM,cAAc;AAClB,eAAa;AACb,SAAO,QAAQ;AAKf,MAAI,CAAC,sBACH,mBAAkB,IAAI,0BAA0B,CAAC;;AAIrD,QAAO;EAAE;EAAO;EAAW;EAAQ;;;;;ACnGrC,qBAAqBC,MAAaC,QAAe"}
@@ -1,10 +1,10 @@
1
1
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
2
2
  import { BaseError, UnavailableInServerSideError, getDefaultClient, getWalletAccounts, refreshAuth } from "@dynamic-labs-sdk/client";
3
- import { getCore } from "@dynamic-labs-sdk/client/core";
3
+ import { MethodNotImplementedError, createDeferredPromise, getCore, isServerSideRendering } from "@dynamic-labs-sdk/client/core";
4
4
 
5
5
  //#region package.json
6
6
  var name = "@dynamic-labs-sdk/legacy-embedded-wallet-upgrade";
7
- var version = "1.22.1";
7
+ var version = "1.23.1";
8
8
 
9
9
  //#endregion
10
10
  //#region src/errors/InvalidUpgradeBaseUrlError.ts
@@ -266,6 +266,21 @@ const consumeUpgradeRedirect = async ({ url }, client = getDefaultClient()) => {
266
266
  return { status: UPGRADE_STATUS_ERROR };
267
267
  };
268
268
 
269
+ //#endregion
270
+ //#region src/clearUpgradeRedirectParams/clearUpgradeRedirectParams.native.ts
271
+ /**
272
+ * Not supported on React Native — there is no browser address bar to clean.
273
+ * Mirrors `clearSocialRedirectParams` / `clearDeviceRegistrationRedirectParams`
274
+ * on native.
275
+ *
276
+ * @returns Never. Always throws on React Native.
277
+ * @throws {MethodNotImplementedError} Always on React Native.
278
+ * @see consumeUpgradeRedirect
279
+ */
280
+ const clearUpgradeRedirectParams = () => {
281
+ throw new MethodNotImplementedError("clearUpgradeRedirectParams");
282
+ };
283
+
269
284
  //#endregion
270
285
  //#region src/subscribeToUpgradeCompletion/subscribeToUpgradeCompletion.ts
271
286
  const isUpgradeCompleteMessage = (data) => typeof data === "object" && data !== null && "type" in data && data.type === UPGRADE_COMPLETE_MESSAGE_TYPE && "status" in data && (data.status === UPGRADE_STATUS_SUCCESS || data.status === UPGRADE_STATUS_ERROR);
@@ -356,10 +371,116 @@ const openUpgradeIframe = ({ container, redirectUrl, baseUrl }, client = getDefa
356
371
  throw new UpgradeIframeUnavailableInReactNativeError();
357
372
  };
358
373
 
374
+ //#endregion
375
+ //#region src/errors/UpgradePopupBlockedError.ts
376
+ var UpgradePopupBlockedError = class extends BaseError {
377
+ constructor() {
378
+ super({
379
+ cause: null,
380
+ code: "upgrade_popup_blocked_error",
381
+ docsUrl: null,
382
+ name: "UpgradePopupBlockedError",
383
+ shortMessage: "Upgrade popup was blocked by the browser. Call openUpgradePopup directly from a user gesture (e.g. a click handler) so the browser allows the window to open."
384
+ });
385
+ }
386
+ };
387
+
388
+ //#endregion
389
+ //#region src/errors/UpgradePopupClosedError.ts
390
+ var UpgradePopupClosedError = class extends BaseError {
391
+ constructor() {
392
+ super({
393
+ cause: null,
394
+ code: "upgrade_popup_closed_error",
395
+ docsUrl: null,
396
+ name: "UpgradePopupClosedError",
397
+ shortMessage: "Upgrade popup was closed before the upgrade completed"
398
+ });
399
+ }
400
+ };
401
+
402
+ //#endregion
403
+ //#region src/openUpgradePopup/openUpgradePopup.ts
404
+ const UPGRADE_POPUP_TARGET = "dynamic-embedded-wallet-upgrade";
405
+ const DEFAULT_WINDOW_FEATURES = "popup=yes,width=420,height=640";
406
+ const POPUP_CLOSED_POLL_INTERVAL_MS = 500;
407
+ /**
408
+ * Runs the upgrade path in a browser popup window.
409
+ *
410
+ * Opens the hosted upgrade app with `window.open`, wires the same
411
+ * origin-checked completion handshake as {@link openUpgradeIframe}, and
412
+ * refreshes the session on success. `completed` resolves with the outcome once
413
+ * the app reports back; it rejects with {@link UpgradePopupClosedError} if the
414
+ * user closes the popup first. Because popup blockers reject windows opened
415
+ * outside a user gesture, **call this synchronously from a click handler** — do
416
+ * no `await` before it. If the browser blocks the popup (window.open returns
417
+ * `null`), it throws {@link UpgradePopupBlockedError} synchronously.
418
+ *
419
+ * Prefer {@link openUpgradeIframe} when you want the flow embedded in your own
420
+ * modal/sheet; use the popup when a separate window is preferable.
421
+ *
422
+ * @example
423
+ * ```ts
424
+ * // in a click handler — no awaits before openUpgradePopup
425
+ * const session = openUpgradePopup();
426
+ * try {
427
+ * const { status } = await session.completed;
428
+ * } catch (error) {
429
+ * // UpgradePopupClosedError when the user dismissed the popup
430
+ * }
431
+ * ```
432
+ * @param [params] - Popup options.
433
+ * @param [params.redirectUrl] - Absolute https completion URL; defaults to `window.location.href`.
434
+ * @param [params.baseUrl] - Upgrade app base URL; defaults to the production app.
435
+ * @param [params.webOptions.popupFeatures] - `window.open` feature string; defaults to a small window.
436
+ * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.
437
+ * @returns A session handle exposing a `close` function and the `completed` promise.
438
+ * @throws {UpgradePopupBlockedError} When the browser blocks the popup (`window.open` returns null).
439
+ * @throws {UnavailableInServerSideError} When called during SSR (no window to open from).
440
+ * @see openUpgradeIframe
441
+ * @see subscribeToUpgradeCompletion
442
+ */
443
+ const openUpgradePopup = ({ baseUrl, redirectUrl, webOptions } = {}, client = getDefaultClient()) => {
444
+ if (isServerSideRendering()) throw new UnavailableInServerSideError("openUpgradePopup");
445
+ const url = buildUpgradeUrl({
446
+ baseUrl,
447
+ redirectUrl
448
+ }, client);
449
+ const popup = window.open(url, UPGRADE_POPUP_TARGET, webOptions?.popupFeatures ?? DEFAULT_WINDOW_FEATURES);
450
+ if (popup === null) throw new UpgradePopupBlockedError();
451
+ const completed = createDeferredPromise();
452
+ completed.promise.catch(() => void 0);
453
+ let hasReceivedCompletion = false;
454
+ const poll = {};
455
+ const unsubscribe = subscribeToUpgradeCompletion({
456
+ baseUrl,
457
+ onComplete: (outcome) => {
458
+ completed.resolve(outcome);
459
+ clearInterval(poll.id);
460
+ },
461
+ onReceived: () => {
462
+ hasReceivedCompletion = true;
463
+ }
464
+ }, client);
465
+ const close = () => {
466
+ unsubscribe();
467
+ clearInterval(poll.id);
468
+ if (!popup.closed) popup.close();
469
+ if (!hasReceivedCompletion) completed.reject(new UpgradePopupClosedError());
470
+ };
471
+ poll.id = setInterval(() => {
472
+ if (popup.closed) close();
473
+ }, POPUP_CLOSED_POLL_INTERVAL_MS);
474
+ return {
475
+ close,
476
+ completed: completed.promise
477
+ };
478
+ };
479
+
359
480
  //#endregion
360
481
  //#region src/exports/index.ts
361
482
  assertPackageVersion(name, version);
362
483
 
363
484
  //#endregion
364
- export { buildUpgradeUrl, consumeUpgradeRedirect, getWalletsRequiringUpgrade, hasWalletsRequiringUpgrade, openUpgradeIframe, startUpgradeRedirect, subscribeToUpgradeCompletion };
485
+ export { buildUpgradeUrl, clearUpgradeRedirectParams, consumeUpgradeRedirect, getWalletsRequiringUpgrade, hasWalletsRequiringUpgrade, openUpgradeIframe, openUpgradePopup, startUpgradeRedirect, subscribeToUpgradeCompletion };
365
486
  //# sourceMappingURL=index.native.esm.js.map