Prerequisites
Before this page: users who sign in to your app (see Post-login user setup) and a Dynamic environment with WaaS enabled.What you’ll build
Some users may still hold an earlier, legacy generation of embedded wallet that should be moved onto Dynamic WaaS. Dynamic provides a ready-made upgrade app that performs the upgrade — the wallet keeps the same address. The@dynamic-labs-sdk/legacy-embedded-wallet-upgrade package wraps the whole flow so you only call functions — it derives the environment from your client, builds the app URL, validates the return URL, and handles the completion handshake. Your job is to:
- Detect which users need the upgrade.
- Route them to the upgrade app — by redirect, by embedding it, or by popup.
- React when the upgrade finishes.
Install
The React entry point (
/react) has react and @dynamic-labs-sdk/react-hooks as optional peer dependencies. Non-React apps import the root and never pull React in.1. Detect who needs the upgrade
Two synchronous helpers tell you whether the signed-in user has any wallet that needs upgrading. They read the environment and wallets from your client, so single-client apps call them with no arguments.- TypeScript
- React
Option A — Redirect to the app
Navigate the user to the upgrade app, then read the outcome when they return.startUpgradeRedirect builds the URL and navigates; consumeUpgradeRedirect reads and strips the result parameter, refreshes the session on success, and returns the outcome (null when the user didn’t just come back from an upgrade).
- TypeScript
- React
Option B — Embed the app (iframe / WebView)
Render the app in an iframe or WebView instead of navigating away. When embedded, the app posts an origin-checked completion message instead of redirecting, so your page can react and close the embed. The package owns the message contract; you keep full control of the surrounding UI (e.g. your bottom sheet or modal).- TypeScript
- React
- React Native
openUpgradeIframe appends an iframe into a container you provide and resolves completed when the app reports done (refreshing the session on success). Call close() if the user dismisses your sheet first.Option C — Popup (new window)
Open the app in a popup window instead of navigating away or embedding it. Like the iframe path, the app posts an origin-checked completion message back — here to the window that opened it — so the current page never unloads. Reach for this when a full-page redirect is too heavy but you don’t want the app inline.- TypeScript
- React
openUpgradePopup opens the window synchronously and resolves completed when the app reports done (refreshing the session on success). completed rejects with an UpgradePopupClosedError if the user closes the popup first, and the call throws an UpgradePopupBlockedError if the browser blocks it.Hosting the app
By default every helper points at Dynamic’s hosted upgrade app. You can run it three ways:- Dynamic-hosted — use the shared Dynamic-hosted deployment as-is (the default; pass nothing). It lives at
https://waas-migration-dynamic-xyz.vercel.app. - Your own subdomain — point a CNAME (e.g.
upgrade.yourapp.com) at the Dynamic-hosted app (waas-migration-dynamic-xyz.vercel.app) so it runs on your own domain and branding, then reach out to Dynamic so we can add your custom domain to the deployment (otherwise it won’t serve on your CNAME). - Fork & self-host — clone the upgrade app repo, build, and host it yourself.
baseUrl — every entry point accepts it:
- TypeScript
- React
Required: allowlist the app’s origin (CORS)
Add the origin serving the app to your environment’s allowed origins in the Dynamic dashboard, or the app’s calls will be blocked:- Your own subdomain / self-host → add your origin (e.g.
https://upgrade.yourapp.com). - Dynamic-hosted → add
https://waas-migration-dynamic-xyz.vercel.app.
Smoother UX: skip the extra login
If you serve the app on a subdomain of your app’s domain and your environment uses cookie-based sessions, an already-signed-in user lands in the app already authenticated — no second login. Otherwise the user simply signs in again with the same credential they use in your app.Handling errors
See also
- Post-login user setup — detect upgrade needs alongside other post-login steps
- Connected wallets management — the upgraded wallet appears here with the same address
- Wallet backup & recovery — back up the wallet after upgrading