SyncAuthFlow is gone — migrate the automatic post-login orchestration (onboarding, MFA, device registration, wallet creation) to an explicit chain you own.
This is the biggest behavioral change in the migration. In the React SDK, SyncAuthFlow ran automatically after authentication and chained every remaining setup step for you. The JavaScript SDK does none of this — you decide which steps to run, detect what’s pending, and render each screen.
After a user authenticated, SyncAuthFlow silently orchestrated, in order:
Onboarding / required-field collection
Captcha (when enabled)
MFA enrollment
Device registration
Embedded wallet creation
You never called these — the widget detected what was missing (useSyncOnboardingFlow watched userWithMissingInfo.missingFields, useSyncMfaFlow watched MFA state, etc.) and pushed the matching view.
There is no automatic orchestration. After auth resolves, you run the chain yourself: check each step, show UI for whatever is pending, and let the user in once everything is done.
signed in → required fields? → MFA? → device registration? → embedded wallet? → ready
Each legacy sync hook maps to a detection call you make explicitly:
React SDK (automatic)
JavaScript SDK (you call)
useSyncOnboardingFlow (required fields)
inspect user.missingFields, save with updateUser({ userFields })
Only handle the steps that apply to your app. Every step below is independent and optional — if your app doesn’t use MFA, skip the MFA check; if it has no embedded wallets, skip wallet creation; and so on. Compose only the checks for the features you’ve actually enabled, in the order that fits your flow. The show* functions below are your UI — the SDK owns the logic, you own the screens.
TypeScript
React
import { getDefaultClient, updateUser } from '@dynamic-labs-sdk/client';import { isUserMissingMfaAuth } from '@dynamic-labs-sdk/client';import { isDynamicWaasEnabled, getChainsMissingWaasWalletAccounts, createWaasWalletAccounts,} from '@dynamic-labs-sdk/client/waas';async function runSetup() { const user = getDefaultClient().user; if (!user) return; // Required fields if (user.missingFields?.length) { const values = await showFieldForm(user.missingFields); await updateUser({ userFields: values }); } // MFA enrollment if (isUserMissingMfaAuth()) { await showMfaEnrollment(); } // Embedded wallet creation const missingChains = getChainsMissingWaasWalletAccounts(); if (isDynamicWaasEnabled() && missingChains.length) { await createWaasWalletAccounts({ chains: missingChains }); } // The user is ready — render your app.}
import { useUser } from '@dynamic-labs-sdk/react-hooks';import { isUserMissingMfaAuth } from '@dynamic-labs-sdk/client';import { isDynamicWaasEnabled, getChainsMissingWaasWalletAccounts,} from '@dynamic-labs-sdk/client/waas';export function SetupGate({ children }: { children: React.ReactNode }) { const { data: user } = useUser(); if (!user) return null; if (user.missingFields?.length) return <FieldForm fields={user.missingFields} />; if (isUserMissingMfaAuth()) return <MfaEnrollment />; if (isDynamicWaasEnabled() && getChainsMissingWaasWalletAccounts().length) { return <CreateWallet />; } return <>{children}</>;}
The complete implementation — every step’s UI, recovery-code acknowledgment, device registration, and lazy wallet creation — is in Post-login user setup.