> ## 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.

# Wallet authentication

> Migrate external wallet discovery, connection, and verification from the React SDK to the JavaScript SDK.

Connecting an external wallet becomes an explicit choice between *connecting* and *connecting + verifying*, and the multi-wallet prompts the React SDK rendered are now yours to build. This page maps the APIs and links to the implementation guides.

## Wallet discovery

The catalogue of available wallet providers moves from `useWalletOptions` to a single function.

| React SDK            | JavaScript SDK                                                   |
| -------------------- | ---------------------------------------------------------------- |
| `useWalletOptions()` | `getWalletOptionsCatalogue()` / `useGetWalletOptionsCatalogue()` |

Each entry carries the provider `key`, display name, icon, and `installationUrls` so you can render install links for wallets the user doesn't have. For the full wallet picker (search, install links, deeplinks), see [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets).

## Connect vs. connect-and-verify

The React SDK decided when to prompt for a signature. Now you choose explicitly:

* `connectWithWalletProvider({ walletProviderKey })` — connect only (read the address, no signature).
* `connectAndVerifyWithWalletProvider({ walletProviderKey })` — connect and prompt for a sign-in signature, proving ownership and linking the wallet to the user.

| React SDK                           | JavaScript SDK                                                                     |
| ----------------------------------- | ---------------------------------------------------------------------------------- |
| `primaryWallet.connector.connect()` | `connectWithWalletProvider()` / `useConnectWithWalletProvider()`                   |
| authenticate connected wallet       | `connectAndVerifyWithWalletProvider()` / `useConnectAndVerifyWithWalletProvider()` |
| `isAuthenticatedWithAWallet`        | `isWalletAccountVerified({ walletAccount })`                                       |

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import {
      connectAndVerifyWithWalletProvider,
    } from '@dynamic-labs-sdk/client';

    const walletAccount = await connectAndVerifyWithWalletProvider({
      walletProviderKey,
    });
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useConnectAndVerifyWithWalletProvider } from '@dynamic-labs-sdk/react-hooks';

    const { mutate: connectAndVerify } = useConnectAndVerifyWithWalletProvider();

    connectAndVerify(
      { walletProviderKey },
      {
        onSuccess: (walletAccount) => {
          // The wallet is connected and verified.
        },
        onError: (error) => {
          // Render your own error UI.
        },
      },
    );
    ```
  </Tab>
</Tabs>

## Hardware wallets

The dedicated hardware-wallet selection view is gone; check support and account type with functions.

| React SDK                      | JavaScript SDK                               |
| ------------------------------ | -------------------------------------------- |
| hardware wallet selection view | `canConnectWithHardwareWallet()`             |
| —                              | `isHardwareWalletAccount({ walletAccount })` |

## Multi-wallet

Automatic multi-wallet prompts (a new wallet detected, switching the active wallet) are gone, and the SDK doesn't track a selected wallet for you. Read the full set with `getWalletAccounts()` and build your own selection UI — see [Connected wallets management](/docs/javascript/building-ui/connected-wallets-management).

## Errors you now own

The React SDK rendered built-in screens for these cases; in the JavaScript SDK you catch the typed error and render your own UI.

| Case                                  | JavaScript SDK                                | Build it in                                                                        |
| ------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------- |
| Wallet already linked to another user | catch `WalletAlreadyLinkedToAnotherUserError` | [Account conflict resolution](/docs/javascript/building-ui/account-conflict-resolution) |
| Sanctioned / screened wallet blocked  | catch `WalletScreeningBlockedError`           | [Handling blocked wallets](/docs/javascript/building-ui/blocked-wallet-screening)       |

```typescript theme={"system"}
import {
  connectAndVerifyWithWalletProvider,
  WalletAlreadyLinkedToAnotherUserError,
  WalletScreeningBlockedError,
} from '@dynamic-labs-sdk/client';

try {
  await connectAndVerifyWithWalletProvider({ walletProviderKey });
} catch (error) {
  if (error instanceof WalletScreeningBlockedError) {
    // showAccessDenied is your implementation.
    showAccessDenied();
  } else if (error instanceof WalletAlreadyLinkedToAnotherUserError) {
    // showWalletAlreadyLinked is your implementation.
    showWalletAlreadyLinked();
  } else {
    throw error;
  }
}
```

<Note>
  Wallet screening (Chainalysis sanctions checks) still runs server-side during verification and is configured per environment in the dashboard — nothing changes there. What changes is that you handle the blocked result and render the UI. The token-gating (`gate_blocked`) and allowlist (`missing_from_list`) cases are still surfaced via their raw API error codes.
</Note>

## See also

* [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets)
* [Connected wallets management](/docs/javascript/building-ui/connected-wallets-management)
* [Account conflict resolution](/docs/javascript/building-ui/account-conflict-resolution)
* [Handling blocked wallets](/docs/javascript/building-ui/blocked-wallet-screening)
* Post-login user setup
