Skip to main content

Prerequisites

Before this page: create and initialize a Dynamic client (see Creating a Dynamic client), and register a chain extension so wallet providers are available (see Adding extensions). External wallets only appear once a chain extension (EVM, Solana, etc.) is registered.

What you’ll build

A “connect wallet” experience: show the wallet providers available in the user’s browser, connect to the one they pick, and — when you need proof they own it — verify ownership. You’ll build the provider list and the connect button, wired to the SDK’s wallet functions. Two levels of connection:
  • Connect — attach the wallet so you can read its address and prompt for signatures. Use this when you just need to interact with a wallet.
  • Connect and verify — connect, then have the user sign a message proving ownership. Verifying links the wallet to the signed-in user (or signs them in). Use this when the wallet must be a trusted credential.

Listing available providers

getAvailableWalletProvidersData returns the providers detected for the registered chains, each with a key, groupKey, and metadata (display name and icon).
import {
  getAvailableWalletProvidersData,
  connectAndVerifyWithWalletProvider,
} from '@dynamic-labs-sdk/client';

function renderWalletList(container: HTMLElement) {
  const providers = getAvailableWalletProvidersData();

  container.replaceChildren();
  for (const provider of providers) {
    const button = document.createElement('button');
    button.type = 'button';

    const icon = document.createElement('img');
    icon.src = provider.metadata.icon;
    icon.alt = '';
    icon.width = 24;
    button.append(icon, document.createTextNode(provider.metadata.displayName));

    button.addEventListener('click', () => connect(provider.key));
    container.append(button);
  }
}

async function connect(walletProviderKey: string) {
  // showConnected / showError are your implementation.
  try {
    const walletAccount = await connectAndVerifyWithWalletProvider({
      walletProviderKey,
    });
    showConnected(walletAccount);
  } catch (error) {
    showError(error);
  }
}
Providers from different chains that represent the same wallet share a groupKey. Group your UI by groupKey if you want one row per wallet (for example, one “MetaMask” entry) instead of one row per chain.

Connect without verifying

When you only need to read an address or request signatures — not prove ownership — use connectWithWalletProvider. It returns the connected WalletAccount without asking the user to sign.
import { connectWithWalletProvider } from '@dynamic-labs-sdk/client';

async function connectOnly(walletProviderKey: string) {
  const walletAccount = await connectWithWalletProvider({ walletProviderKey });
  // showAddress is your implementation.
  showAddress(walletAccount.address);
}
Verifying a wallet that already belongs to a different account surfaces a conflict. Handle it with the flow in Account conflict resolution.

Handling errors

Error / situationWhenWhat to do
WalletAlreadyLinkedToAnotherUserErrorVerifying a wallet that’s on another accountSee Account conflict resolution.
WalletScreeningBlockedErrorWallet blocked by compliance screeningSee Handling blocked wallets.
UserRejectedErrorUser dismissed the wallet’s connect/sign promptReturn the user to the list so they can retry or pick another wallet.
Empty provider listNo chain extension registered, or no wallet detectedConfirm a chain extension is registered; prompt the user to install a wallet.

See also

Last modified on July 10, 2026