Right after the wallet is created, if a password is required, prompt for one and set it.
TypeScript
React
import { getDefaultClient } from '@dynamic-labs-sdk/client';import { isPasswordRequiredForWaasWallets, setWaasWalletAccountPassword,} from '@dynamic-labs-sdk/client/waas';import type { WalletAccount } from '@dynamic-labs-sdk/client';async function protectWallet(walletAccount: WalletAccount) { // isPasswordRequiredForWaasWallets throws if no user is authenticated, so // only call it once the user is signed in. if (!getDefaultClient().user) return; if (!isPasswordRequiredForWaasWallets()) return; // promptForNewPassword is your implementation — collect + confirm a password. const password = await promptForNewPassword(); await setWaasWalletAccountPassword({ password, walletAccount });}
import { isPasswordRequiredForWaasWallets } from '@dynamic-labs-sdk/client/waas';import type { WalletAccount } from '@dynamic-labs-sdk/client';import { useSetWaasWalletAccountPassword, useUser,} from '@dynamic-labs-sdk/react-hooks';function SetPassword({ walletAccount }: { walletAccount: WalletAccount }) { const user = useUser(); const { mutateAsync: setPassword, isPending } = useSetWaasWalletAccountPassword(); // isPasswordRequiredForWaasWallets throws before auth settles, so wait for a // signed-in user before calling it. if (!user) return null; if (!isPasswordRequiredForWaasWallets()) return null; return ( <form onSubmit={async (event) => { event.preventDefault(); const password = new FormData(event.currentTarget).get('password'); await setPassword({ password: String(password), walletAccount }); }} > <input name="password" type="password" autoComplete="new-password" /> <button type="submit" disabled={isPending}> {isPending ? 'Saving…' : 'Set password'} </button> </form> );}
The password can’t be recovered if the user forgets it. Make that clear in your UI, and pair it with a backup & recovery option so users aren’t locked out.
When a returning user signs in on a device that hasn’t unlocked the wallet yet, prompt for the password before the wallet can sign. Use getWalletRecoveryState to detect this: its walletReadyState is 'encrypted' when this device’s key share is still locked (prompt to unlock) and 'ready' once it’s unlocked. Check it after sign-in so you only show the prompt when it’s actually needed.
TypeScript
React
import { getWalletRecoveryState, unlockWallet } from '@dynamic-labs-sdk/client/waas';import type { WalletAccount } from '@dynamic-labs-sdk/client';async function unlockIfNeeded(walletAccount: WalletAccount) { const { walletReadyState } = await getWalletRecoveryState({ walletAccount }); // 'encrypted' means this device's key share is still locked; 'ready' means // it's already unlocked and can sign. if (walletReadyState !== 'encrypted') return; // promptForPassword is your implementation. const password = await promptForPassword(); try { await unlockWallet({ password, walletAccount }); // showUnlocked is your implementation. showUnlocked(); } catch { // showError is your implementation — likely a wrong password. showError("That password didn't work. Try again."); }}