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

# Build a WalletProvider

> Implement and register a custom WalletProvider with the Dynamic JavaScript SDK.

A `WalletProvider` connects a wallet to the SDK. It is for companies that control a wallet app or browser extension and want Dynamic's SDK to route signing to it. At minimum it must implement `chain`, `key`, `groupKey`, `metadata`, `walletProviderType`, `getActiveNetworkId`, and `getConnectedAddresses`.

## Minimal WalletProvider

```typescript theme={"system"}
import { WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
import type { WalletProvider } from "@dynamic-labs-sdk/client/core";
import {
  formatWalletProviderGroupKey,
  formatWalletProviderKey,
} from "@dynamic-labs-sdk/client/core";

const MY_WALLET_DISPLAY_NAME = "My Wallet";

const MY_WALLET_KEY = formatWalletProviderKey({
  // Replace with the chain your wallet supports.
  // Create a separate provider for each chain you support.
  chain: "EVM",
  displayName: MY_WALLET_DISPLAY_NAME,
  walletProviderType: WalletProviderEnum.BrowserExtension,
});

const myWalletProvider: WalletProvider = {
  // Replace with the chain your wallet supports.
  chain: "EVM",
  key: MY_WALLET_KEY,
  groupKey: formatWalletProviderGroupKey(MY_WALLET_DISPLAY_NAME),
  metadata: {
    displayName: MY_WALLET_DISPLAY_NAME,
    icon: "https://example.com/icon.svg",
  },
  walletProviderType: WalletProviderEnum.BrowserExtension,

  // Replace with your wallet connection logic.
  connect: async () => ({
    addresses: [{ address: "0x..." }],
  }),

  // Replace with your wallet API calls.
  getConnectedAddresses: async () => ({
    addresses: ["0x..."],
  }),

  // Replace with your wallet API calls.
  getActiveNetworkId: async () => ({
    networkId: "1",
  }),

  // Replace with your wallet API calls.
  signMessage: async ({ message }) => ({
    signature: "0x...",
  }),
};
```

## Register the provider

Extensions register wallet providers through the `WalletProviderRegistry`. Set a priority that reflects how the wallet is integrated. Higher-priority registrations win when the same `key` is registered more than once.

```typescript theme={"system"}
import {
  getDefaultClient,
  getWalletProviderRegistry,
  hasExtension,
  registerExtension,
  WalletProviderPriority,
} from "@dynamic-labs-sdk/client/core";
import type { DynamicClient } from "@dynamic-labs-sdk/client";

const MY_WALLET_EXTENSION_KEY = "myWallet";

const myWalletProvider = {
  /* ... wallet provider from above ... */
};

export const addMyWalletExtension = (
  client: DynamicClient = getDefaultClient()
): void => {
  if (hasExtension({ extensionKey: MY_WALLET_EXTENSION_KEY }, client)) {
    return;
  }

  registerExtension({ extensionKey: MY_WALLET_EXTENSION_KEY }, client);

  getWalletProviderRegistry(client).register({
    priority: WalletProviderPriority.WALLET_SDK,
    walletProvider: myWalletProvider,
  });
};
```

`WalletProviderPriority.WALLET_SDK` is the highest priority. Use it when you control the wallet's own SDK. See [Wallet provider priority](/docs/javascript/reference/creating-extensions/services/wallet-provider-priority) for the full priority levels and registry replacement behavior.

<Warning>
  The registry stores one provider per `key`. If a provider with the same `key` is registered again, the higher-priority registration wins. Keep `key` stable by using `formatWalletProviderKey`.
</Warning>

## One provider per chain

A `WalletProvider` is chain-specific. If your wallet supports more than one chain, create one provider per chain and register all of them from the same extension.

For example, a wallet that supports EVM and Solana would have two providers:

```typescript theme={"system"}
import { getWalletProviderRegistry } from "@dynamic-labs-sdk/client/core";

const evmProvider: WalletProvider = {
  chain: "EVM",
  key: formatWalletProviderKey({
    chain: "EVM",
    displayName: MY_WALLET_DISPLAY_NAME,
    walletProviderType: WalletProviderEnum.BrowserExtension,
  }),
  /* ... other fields ... */
};

const solanaProvider: WalletProvider = {
  chain: "SOL",
  key: formatWalletProviderKey({
    chain: "SOL",
    displayName: MY_WALLET_DISPLAY_NAME,
    walletProviderType: WalletProviderEnum.BrowserExtension,
  }),
  /* ... other fields ... */
};

getWalletProviderRegistry(client).register({
  priority: WalletProviderPriority.WALLET_SDK,
  walletProvider: evmProvider,
});

getWalletProviderRegistry(client).register({
  priority: WalletProviderPriority.WALLET_SDK,
  walletProvider: solanaProvider,
});
```

## Connect the wallet

The custom wallet provider is only available to the SDK after your extension has registered it. In the app that consumes the extension, create a `DynamicClient`, add the extension, and then connect.

```typescript theme={"system"}
import {
  createDynamicClient,
  connectAndVerifyWithWalletProvider,
} from "@dynamic-labs-sdk/client";
import { addMyWalletExtension } from "my-wallet-extension";

const client = createDynamicClient({
  environmentId: "YOUR_ENVIRONMENT_ID",
});

// Register the wallet provider with this client.
addMyWalletExtension(client);

const walletAccount = await connectAndVerifyWithWalletProvider(
  { walletProviderKey: MY_WALLET_KEY },
  client
);

console.log("Connected and verified:", walletAccount.address);
```

Use `connectWithWalletProvider` instead of `connectAndVerifyWithWalletProvider` if you only want to connect without verifying ownership. You can also discover the provider with `getAvailableWalletProvidersData` once the extension is registered.
