waitForAuthSuccess
Returns a promise that resolves with the authenticated user once the authSuccess event fires. Use this when you need to ensure authentication is fully complete — including MFA and other intermediate steps — before proceeding (for example, before loading wallets or accessing user data).
Before this: set up the Dynamic client (see Setting up the Dynamic Client).
Why use this instead of listening to events?
Listening for authSuccess with dynamicClient.auth.on works, but it requires manual cleanup and doesn’t handle edge cases like MFA flows where authentication pauses for user input. waitForAuthSuccess wraps this into a single promise that:
- Resolves when authentication completes (even after MFA or other intermediate steps)
- Rejects when authentication fails or is cancelled
- Supports an optional timeout
Usage
import { dynamicClient } from '<path to client file>';
const user = await dynamicClient.auth.waitForAuthSuccess();
// Authentication complete — user and wallets are available
Parameters
| Parameter | Type | Description |
|---|
timeout | number | Maximum time in milliseconds to wait. Rejects with an error if exceeded. |
Pass options as an object:
dynamicClient.auth.waitForAuthSuccess({ timeout: 60_000 });
Returns
Promise<UserProfile> — Resolves with the authenticated user profile.
Behavior
- User not yet authenticated: Listens for
authSuccess and resolves when it fires. If authFailed fires first, the promise rejects.
- User already authenticated: Waits briefly (500 ms grace period) for an incoming
authSuccess event. If no event arrives, resolves with the current authenticated user. This handles the case where authentication completed moments before the call.
- Timeout: If
timeout is set and neither authSuccess nor authFailed fires within that window, the promise rejects with a timeout error.
Examples
Wait for authentication before loading wallets
With UI auth flow
With email OTP
import { dynamicClient } from '<path to client file>';
import { useState } from 'react';
import { View, Button, Text } from 'react-native';
const LoginScreen = () => {
const [status, setStatus] = useState('');
const handleLogin = async () => {
dynamicClient.ui.auth.show();
try {
const user = await dynamicClient.auth.waitForAuthSuccess();
setStatus(`Authenticated: ${user.email}`);
// Safe to access wallets now
} catch (error) {
setStatus(`Auth failed: ${error.message}`);
}
};
return (
<View>
<Button title="Log in" onPress={handleLogin} />
{status ? <Text>{status}</Text> : null}
</View>
);
};
import { dynamicClient } from '<path to client file>';
import { useState } from 'react';
import { View, TextInput, Button, Text } from 'react-native';
const EmailLoginScreen = () => {
const [email, setEmail] = useState('');
const [otp, setOtp] = useState('');
const [otpSent, setOtpSent] = useState(false);
const handleSendOTP = async () => {
await dynamicClient.auth.email.sendOTP(email);
setOtpSent(true);
};
const handleVerifyOTP = async () => {
await dynamicClient.auth.email.verifyOTP(otp);
// Wait for auth to fully complete (including MFA if required)
const user = await dynamicClient.auth.waitForAuthSuccess();
// Now safe to check embedded wallet status
const hasWallet = dynamicClient.wallets.embedded.hasWallet;
console.log('Has embedded wallet:', hasWallet);
};
return (
<View>
{!otpSent ? (
<View>
<TextInput
value={email}
onChangeText={setEmail}
placeholder="Enter your email"
/>
<Button title="Send OTP" onPress={handleSendOTP} />
</View>
) : (
<View>
<TextInput
value={otp}
onChangeText={setOtp}
placeholder="Enter OTP"
/>
<Button title="Verify OTP" onPress={handleVerifyOTP} />
</View>
)}
</View>
);
};
Error handling
The promise rejects in three cases:
| Scenario | Error message |
|---|
| User cancels authentication | Authentication was cancelled by the user |
| Authentication fails | Authentication failed: <reason> |
| Timeout exceeded | waitForAuthSuccess timed out |
Last modified on May 7, 2026