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

# Connecting and Verifying a Wallet

In Dynamic, we treat each chain (EVM, SOL, etc.) and each wallet app (or wallet provider) as a separate entity, and when connected/verified,
will create a separate wallet account.

There are 4 ways to connect and verify a wallet:

1. Connect any wallet by its wallet options catalogue key

   In this case, the SDK selects an installed provider, a URI pairing, or the wallet's in-app browser. The connected wallet account is unverified until you complete the verification step.

2. Connect and verify in a single SDK call

   In this case, the wallet account is only added to the wallet accounts list once it passes the verification step.

3. Connect without verifying

   In this case, the wallet account is added to the wallet accounts list as soon as the user accepts the connection, but it will only be persisted in the local session and not associated to a Dynamic user.

4. Verify a wallet account that has been connected but not verified before

   In this case, the wallet account remains in the wallet accounts list, no matter if the verification step is successful or not.

   The difference is that the wallet account will have a new `verifiedCredentialId` property, be persisted in the Dynamic server and associated to a Dynamic user.

## 1. Connect any wallet by catalogue key

Use `connectWalletOption` when you have a wallet options catalogue key, such as `'metamask'`, instead of a wallet provider key. The SDK selects the connection path that the wallet supports on the user's device:

* An installed wallet provider when the user has the wallet.
* A URI pairing through WalletConnect or the MetaMask SDK, handed to `onConnectionUri`.
* The wallet's own in-app browser through `handleWalletBrowserRedirect`.

The function returns an unverified wallet account. Pair it with `verifyWalletAccount` in [section 4](#4-verify-a-connected-wallet-account) to link it to the user. See [Connect a wallet by catalogue key](https://docs.dynamic.xyz/docs/javascript/reference/wallets/connect-wallet-option.md) for the full reference.

> [tab] JavaScript
>
> ```javascript theme={"system"}
> import {
>   connectWalletOption,
>   isMobile,
>   redirectToInAppBrowser,
> } from '@dynamic-labs-sdk/client';
>
> const walletAccount = await connectWalletOption({
>   handleWalletBrowserRedirect: ({ chain, walletKey }) =>
>     redirectToInAppBrowser({
>       appUrl: window.location.href,
>       chain,
>       walletKey,
>     }),
>   onConnectionUri: ({ uri }) => {
>     if (isMobile()) {
>       window.location.href = uri;
>       return;
>     }
>
>     renderQrCode(uri);
>   },
>   walletKey: 'metamask',
> });
>
> console.log(`Connected: ${walletAccount.address}`);
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { isMobile } from '@dynamic-labs-sdk/client';
> import { useConnectWalletOption } from '@dynamic-labs-sdk/react-hooks';
>
> function ConnectWalletButton() {
>   const { mutate: connect, isPending } = useConnectWalletOption();
>
>   return (
>     <button
>       onClick={() =>
>         connect({
>           onConnectionUri: ({ uri }) => {
>             if (isMobile()) {
>               window.location.href = uri;
>               return;
>             }
>
>             renderQrCode(uri);
>           },
>           walletKey: 'metamask',
>         })
>       }
>       disabled={isPending}
>     >
>       {isPending ? 'Connecting...' : 'Connect wallet'}
>     </button>
>   );
> }
> ```

## 2. Connect and verify a wallet in a single SDK call

> [!NOTE]
>
> On mobile, `connectAndVerifyWithWalletProvider` throws a `DeeplinkConnectAndVerifyUnsupportedError`
> for deep link wallet providers (e.g. Phantom redirect). This is because it triggers two sequential
> deep links and iOS will not honor the second one. Use options 3 and 4 below to connect and verify
> separately. See the [Phantom Redirect Extension docs](https://docs.dynamic.xyz/docs/javascript/reference/solana/phantom-redirect-extension.md#connect-and-verify-on-mobile)
> for a full example.

> [tab] JavaScript
>
> ```javascript theme={"system"}
> import { connectAndVerifyWithWalletProvider } from '@dynamic-labs-sdk/client';
>
> const signInWithWallet = async (key) => {
>   try {
>     const walletAccount = await connectAndVerifyWithWalletProvider({ walletProviderKey: key });
>     console.log(`Connected and verified: ${walletAccount.address}`);
>   } catch (error) {
>     console.error('Error connecting or verifying wallet: ', error);
>   }
> };
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { useConnectAndVerifyWithWalletProvider } from '@dynamic-labs-sdk/react-hooks';
>
> function ConnectWalletButton({ walletProviderKey }: { walletProviderKey: string }) {
>   // On success, `useGetWalletAccounts()` consumers re-render automatically.
>   const { mutate: connectAndVerify, isPending, error } =
>     useConnectAndVerifyWithWalletProvider();
>
>   return (
>     <>
>       <button
>         onClick={() => connectAndVerify({ walletProviderKey })}
>         disabled={isPending}
>       >
>         {isPending ? 'Connecting…' : 'Connect'}
>       </button>
>       {error && <p>Error: {error.message}</p>}
>     </>
>   );
> }
> ```

## 3. Connect a wallet without verifying it

> [tab] JavaScript
>
> ```javascript theme={"system"}
> import { connectWithWalletProvider } from '@dynamic-labs-sdk/client';
>
> const signInWithWallet = async (key) => {
>   try {
>     const walletAccount = await connectWithWalletProvider({ walletProviderKey: key });
>     console.log(`Connected: ${walletAccount.address}`);
>   } catch (error) {
>     console.error('Error connecting wallet: ', error);
>   }
> };
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { useConnectWithWalletProvider } from '@dynamic-labs-sdk/react-hooks';
>
> function ConnectButton({ walletProviderKey }: { walletProviderKey: string }) {
>   // `data` is the connected (session-only, unverified) wallet account.
>   const { mutate: connect, data, isPending } = useConnectWithWalletProvider();
>
>   return (
>     <button onClick={() => connect({ walletProviderKey })} disabled={isPending}>
>       {data ? `Connected: ${data.address}` : 'Connect'}
>     </button>
>   );
> }
> ```

## 4. Verify a connected wallet account

You can use this function to verify a wallet account that was connected but not verified before.

> [tab] JavaScript
>
> ```javascript theme={"system"}
> import { verifyWalletAccount } from '@dynamic-labs-sdk/client';
>
> const verifyWallet = async (walletAccount) => {
>   try {
>     const verified = await verifyWalletAccount({ walletAccount });
>     console.log(`Verified: ${verified.address}`);
>   } catch (error) {
>     console.error('Error verifying wallet: ', error);
>   }
> };
> ```

> [tab] React
>
> ```tsx theme={"system"}
> import { type WalletAccount } from '@dynamic-labs-sdk/client';
> import { useVerifyWalletAccount } from '@dynamic-labs-sdk/react-hooks';
>
> function VerifyButton({ walletAccount }: { walletAccount: WalletAccount }) {
>   const { mutate: verifyWalletAccount, isPending } = useVerifyWalletAccount();
>
>   return (
>     <button
>       onClick={() => verifyWalletAccount({ walletAccount })}
>       disabled={isPending}
>     >
>       {isPending ? 'Verifying…' : 'Verify wallet'}
>     </button>
>   );
> }
> ```

## Hardware wallet connections

Both `connectWithWalletProvider` and `connectAndVerifyWithWalletProvider` accept an optional
`hardwareWalletVendor` parameter to connect via a hardware wallet (e.g., Ledger) through a
compatible software wallet:

```javascript theme={"system"}
import {
  getAvailableWalletProvidersData,
  canConnectWithHardwareWallet,
  connectAndVerifyWithWalletProvider,
} from '@dynamic-labs-sdk/client';

const ledgerProvider = getAvailableWalletProvidersData().find((provider) =>
  canConnectWithHardwareWallet({
    walletProviderKey: provider.key,
    hardwareWalletVendor: 'ledger',
  })
);

if (ledgerProvider) {
  const walletAccount = await connectAndVerifyWithWalletProvider({
    walletProviderKey: ledgerProvider.key,
    hardwareWalletVendor: 'ledger',
  });
}
```

See [Hardware Wallet Support](https://docs.dynamic.xyz/docs/javascript/reference/wallets/hardware-wallets.md) for the full guide,
including how to check support per provider and detect hardware wallet accounts.

## Related functions

* [`connectWalletOption`](https://docs.dynamic.xyz/docs/javascript/reference/wallets/connect-wallet-option) is the entry point when you have a wallet catalogue key rather than a wallet provider key.
* [Getting Wallet Accounts](https://docs.dynamic.xyz/docs/javascript/reference/wallets/get-wallet-accounts.md)
* [Adding EVM Extensions](https://docs.dynamic.xyz/docs/javascript/reference/evm/adding-evm-extensions.md)
* [Adding Solana Extensions](https://docs.dynamic.xyz/docs/javascript/reference/solana/adding-solana-extensions.md)
* [Wallet Provider Events](https://docs.dynamic.xyz/docs/javascript/reference/wallets/wallet-provider-events.md)
* [Hardware Wallet Support](https://docs.dynamic.xyz/docs/javascript/reference/wallets/hardware-wallets.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.