> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Events Catalog

> Full reference of events emitted by the Dynamic JavaScript client, including payload shapes.

The Dynamic client emits events for authentication state changes, wallet activity, MFA, device registration, checkout transactions, and project settings. Subscribe to any event with [`onEvent`](/javascript/reference/client/on-event) (or [`offEvent`](/javascript/reference/client/off-event) to remove a listener). React apps can use `useOnEvent` from `@dynamic-labs-sdk/react-hooks` for a hook with built-in cleanup.

## Subscribing

```javascript theme={"system"}
import { onEvent } from '@dynamic-labs-sdk/client';

const unsubscribe = onEvent({
  event: 'userChanged',
  listener: ({ user }) => {
    console.log('User changed:', user);
  },
});

// Later — remove the listener
unsubscribe();
```

The `listener` is fully typed against the event name: hover over `event` in your editor to see the payload TypeScript expects.

## Authentication state

State-change events fire whenever a top-level field on the [`DynamicClient`](/javascript/reference/client/create-dynamic-client) changes. They are the primary way to react to login, logout, and JWT refreshes.

| Event                     | Payload                                                                      | When it fires                                                                                                                                                                                                                                                 |
| ------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initStatusChanged`       | `{ initStatus: 'uninitialized' \| 'in-progress' \| 'finished' \| 'failed' }` | Each time client initialization advances. Use `'finished'` to know the client is ready.                                                                                                                                                                       |
| `userChanged`             | `{ user: User \| null }`                                                     | The authenticated user object is set, updated, or cleared (e.g. on logout).                                                                                                                                                                                   |
| `tokenChanged`            | `{ token: string \| null }`                                                  | The JWT changes — on sign in, refresh, or logout.                                                                                                                                                                                                             |
| `sessionExpiresAtChanged` | `{ sessionExpiresAt: Date \| null }`                                         | Session expiry timestamp updates.                                                                                                                                                                                                                             |
| `projectSettingsChanged`  | `{ projectSettings: ProjectSettings \| null }`                               | Dashboard settings are fetched or refreshed.                                                                                                                                                                                                                  |
| `logout`                  | `{ reason: LogoutReason }` (optional)                                        | `logout` is called. `reason` is one of `'user-intent'`, `'token-expired'`, `'user-deleted'`, `'device-revoked'`, `'all-devices-revoked'`, `'session-refresh-unauthorized'`, `'user-refresh-failed'`, `'keychain-migration-failed'`, `'keychain-key-missing'`. |

```javascript theme={"system"}
import { onEvent } from '@dynamic-labs-sdk/client';

onEvent({
  event: 'initStatusChanged',
  listener: ({ initStatus }) => {
    if (initStatus === 'finished') {
      // Safe to call SDK methods that depend on initialization.
    }
  },
});
```

See [Initializing the Dynamic Client](/javascript/reference/client/initialize-dynamic-client) for init-status semantics.

## Wallet accounts and providers

| Event                        | Payload                               | When it fires                                                             |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------- |
| `walletAccountsChanged`      | `{ walletAccounts: WalletAccount[] }` | A wallet is added, removed, verified, or its primary status changes.      |
| `walletProviderRegistered`   | `{ walletProvider: WalletProvider }`  | A wallet provider is registered (typically when a chain extension loads). |
| `walletProviderUnregistered` | `{ walletProviderKey: string }`       | A wallet provider is unregistered.                                        |
| `walletProviderChanged`      | `{ walletProviderKey: string }`       | A registered provider's metadata or capabilities change.                  |

For per-provider events (account changes, chain switches inside a single provider), see [Wallet Provider Events](/javascript/reference/wallets/wallet-provider-events).

```javascript theme={"system"}
import { onEvent } from '@dynamic-labs-sdk/client';

onEvent({
  event: 'walletAccountsChanged',
  listener: ({ walletAccounts }) => {
    console.log(`Connected: ${walletAccounts.length} wallet(s)`);
  },
});
```

## MFA

| Event                  | Payload                                    | When it fires                                                                                          |
| ---------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| `mfaTokenChanged`      | `{ mfaToken: string \| null }`             | The MFA token is issued, refreshed, or cleared.                                                        |
| `mfaCompletionSuccess` | `{ deviceId?: string; mfaToken?: string }` | A user successfully completes an MFA challenge. `deviceId` is `undefined` if a recovery code was used. |
| `mfaCompletionFailure` | `{ deviceId?: string; error: unknown }`    | An MFA challenge fails verification.                                                                   |

See the [MFA overview](/javascript/authentication-methods/mfa/overview) for how these surface in the broader flow.

## Device registration

| Event                                     | Payload     | When it fires                                                                                          |
| ----------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------ |
| `deviceRegistrationCompleted`             | *(no args)* | Device registration completes successfully in the **current** tab.                                     |
| `deviceRegistrationCompletedInAnotherTab` | *(no args)* | Device registration completed in **another** tab — broadcast cross-tab so every tab can refresh state. |

See [Device Registration](/javascript/authentication-methods/device-registration).

## Checkout

| Event                                       | Payload                                                                                                                   | When it fires                                                                          |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `checkoutTransactionExecutionStateChanged`  | `{ transactionId: string; previousState: CheckoutExecutionState; newState: CheckoutExecutionState; timestamp: string }`   | A checkout transaction's execution state advances (queued, executing, executed, etc.). |
| `checkoutTransactionSettlementStateChanged` | `{ transactionId: string; previousState: CheckoutSettlementState; newState: CheckoutSettlementState; timestamp: string }` | A checkout transaction's settlement state advances.                                    |

These let you build a transaction status UI without polling. See the [Fireblocks Flow JavaScript SDK guide](/overview/fireblocks-flow-js-sdk).

## React patterns

Use [`useOnEvent`](/javascript/reference/client/on-event#react-patterns) from `@dynamic-labs-sdk/react-hooks` — it subscribes on mount and cleans up on unmount:

```tsx theme={"system"}
import { useOnEvent } from '@dynamic-labs-sdk/react-hooks';

function LogoutLogger() {
  useOnEvent({
    event: 'logout',
    listener: ({ reason } = {}) => {
      console.log('User logged out:', reason);
    },
  });
  return null;
}
```

For state that should drive re-renders (user, wallet accounts, init status, session), prefer the dedicated hooks (`useUser`, `useGetWalletAccounts`, `useInitStatus`) — they subscribe to the relevant events internally.

## One-time listeners

Use `onceEvent` for a listener that auto-removes after firing once — useful for waiting on initialization or a single MFA completion.

```javascript theme={"system"}
import { onceEvent } from '@dynamic-labs-sdk/client';

onceEvent({
  event: 'initStatusChanged',
  listener: ({ initStatus }) => {
    if (initStatus === 'finished') {
      // runs at most once
    }
  },
});
```

## Type safety

The full event surface is declared globally as `DynamicEvents`, augmented by each module that emits events. `onEvent`, `offEvent`, and `onceEvent` are generic over `keyof DynamicEvents`, so the listener signature is inferred from the event name — there is no central enum to keep in sync.

## Related functions

* [onEvent](/javascript/reference/client/on-event)
* [offEvent](/javascript/reference/client/off-event)
* [Wallet Provider Events](/javascript/reference/wallets/wallet-provider-events)
* [Initializing the Dynamic Client](/javascript/reference/client/initialize-dynamic-client)
