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.
External wallets allow users to sign up and log in using their own wallet (MetaMask, Phantom, Coinbase Wallet, etc.).
Create and Initialize the Dynamic Client
First, install the client package and create a Dynamic Client with your environment ID.
npm install @dynamic-labs-sdk/client
import { createDynamicClient } from '@dynamic-labs-sdk/client';
const dynamicClient = createDynamicClient({
environmentId: 'YOUR_ENVIRONMENT_ID',
metadata: {
name: 'YOUR_APP_NAME',
url: 'YOUR_APP_URL',
iconUrl: 'YOUR_APP_ICON_URL',
},
});
See Creating a Dynamic Client for more details.
Add chain extensions for every chain you want to support
Install and add the extension for each chain you want in your adaptor. Each guide covers installation and how to add that chain’s extension.
The list from getAvailableWalletProvidersData() (below) includes every wallet provider from every extension you added.
Enable those chains in the dashboard
In the Dynamic dashboard, enable each chain you added an extension for (e.g. EVM, Solana, Bitcoin). Available options match the chain extensions above.
Fetch available wallet providers (your adaptor’s options)
Use getAvailableWalletProvidersData to get the full list of wallet providers your adaptor can offer. It includes every chain–wallet combination from the extensions you added (e.g. metamaskevm, metamasksol, phantomevm, phantomsol).
import { getAvailableWalletProvidersData } from ‘@dynamic-labs-sdk/client’;
const walletProvidersData = getAvailableWalletProvidersData();
walletProvidersData.forEach((provider) => {
console.log(provider.key); // e.g., ‘metamaskevm’
console.log(provider.metadata.displayName); // e.g., ‘MetaMask’
console.log(provider.groupKey); // e.g., ‘metamask’ (for grouping)
console.log(provider.chain); // e.g., ‘evm’ or ‘sol’
});
Use useWalletProviders from @dynamic-labs-sdk/react-hooks — it re-renders whenever extensions load or change.import { useWalletProviders } from ‘@dynamic-labs-sdk/react-hooks’;
See Getting Available Wallets to Connect for more details.
Display wallet options in your UI
Each wallet provider includes metadata (display name, icon). Use it to build your wallet selection UI (buttons, list, or modal).
const walletProvidersData = getAvailableWalletProvidersData();
// Example: render wallet buttons
walletProvidersData.map((provider) => (
<button key={provider.key} onClick={() => handleConnect(provider.key)}>
<img src={provider.metadata.iconUrl} alt={provider.metadata.displayName} />
{provider.metadata.displayName}
</button>
));
function WalletList() {
const providers = useWalletProviders(); // hook from above
return (
<ul>
{providers.map((provider) => (
<li key={provider.key}>
<button onClick={() => handleConnect(provider)}>
<img src={provider.metadata.iconUrl} alt={provider.metadata.displayName} />
{provider.metadata.displayName}
</button>
</li>
))}
</ul>
);
}
Connect and verify
When the user picks a wallet from your adaptor UI, use one of these methods. The JS SDK supports three flows depending on when you want verification to occur.
1. Connect and verify in one step
The wallet account is only added after a successful verification signature. Use this for login/signup flows.
import { connectAndVerifyWithWalletProvider } from ‘@dynamic-labs-sdk/client’;
const walletAccount = await connectAndVerifyWithWalletProvider({
walletProviderKey: ‘metamaskevm’,
});
// walletAccount is now verified and associated to a Dynamic user
console.log(walletAccount.accountAddress);
import { connectAndVerifyWithWalletProvider } from ‘@dynamic-labs-sdk/client’;
import { useState } from ‘react’;
function ConnectWalletButton({ walletProviderKey }: { walletProviderKey: string }) {
const [isConnecting, setIsConnecting] = useState(false);
const handleConnect = async () => {
setIsConnecting(true);
try {
const walletAccount = await connectAndVerifyWithWalletProvider({ walletProviderKey });
// walletAccount is now verified — update your app state as needed
console.log(walletAccount.accountAddress);
} finally {
setIsConnecting(false);
}
};
return (
<button onClick={handleConnect} disabled={isConnecting}>
{isConnecting ? ‘Connecting…’ : ‘Connect wallet’}
</button>
);
}
2. Connect without verifying
The wallet account is added to the session but not yet associated to a Dynamic user. Use this to defer verification.
import { connectWithWalletProvider } from ‘@dynamic-labs-sdk/client’;
const walletAccount = await connectWithWalletProvider({
walletProviderKey: ‘metamaskevm’,
});
// walletAccount is connected but not verified (session-only)
import { connectWithWalletProvider } from ‘@dynamic-labs-sdk/client’;
async function handleConnect(walletProviderKey: string) {
const walletAccount = await connectWithWalletProvider({ walletProviderKey });
// walletAccount is connected but not verified (session-only)
}
3. Verify a previously connected account
Verify a wallet that was connected but not yet verified. This associates it with a Dynamic user.
import { verifyWalletAccount } from ‘@dynamic-labs-sdk/client’;
const verifiedWalletAccount = await verifyWalletAccount({
walletAccount,
});
// walletAccount now has a verifiedCredentialId and is associated to a Dynamic user
import { verifyWalletAccount, type WalletAccount } from ‘@dynamic-labs-sdk/client’;
import { useState } from ‘react’;
function VerifyWalletButton({ walletAccount }: { walletAccount: WalletAccount }) {
const [isVerifying, setIsVerifying] = useState(false);
const handleVerify = async () => {
setIsVerifying(true);
try {
await verifyWalletAccount({ walletAccount });
// Wallet is now associated to a Dynamic user
} finally {
setIsVerifying(false);
}
};
return (
<button onClick={handleVerify} disabled={isVerifying}>
{isVerifying ? ‘Verifying…’ : ‘Verify wallet’}
</button>
);
}
See Connecting and Verifying a Wallet for more details.
Get all connected wallet accounts
Retrieve every wallet account the user has connected (across all chains) using getWalletAccounts.
import { getWalletAccounts } from ‘@dynamic-labs-sdk/client’;
const walletAccounts = getWalletAccounts();
walletAccounts.forEach((account) => {
console.log(account.accountAddress);
console.log(account.verifiedCredentialId); // null if not verified
});
Use useWalletAccounts from @dynamic-labs-sdk/react-hooks — it re-renders whenever accounts are added or removed.import { useWalletAccounts } from ‘@dynamic-labs-sdk/react-hooks’;
function WalletAccountsList() {
const walletAccounts = useWalletAccounts();
return (
<ul>
{walletAccounts.map((account) => (
<li key={account.id}>{account.accountAddress}</li>
))}
</ul>
);
}
See Getting Wallet Accounts for more details.