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

# Network switching & validation

> Show the active network, let users switch, and make sure a wallet is on the right network before you transact.

## Prerequisites

Before this page: have a connected wallet (see [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets)). Network operations act on a specific `WalletAccount` that your app supplies.

## What you'll build

Three things most web3 apps need:

* **Show** the wallet's current network.
* **Switch** the wallet to another supported network.
* **Validate** the wallet is on the network your action requires — and switch (or ask the user to) when it isn't.

## Showing the active network

`getActiveNetworkData` returns `{ networkData }` for the wallet's current network — `displayName`, `iconUrl`, `nativeCurrency`, and the `networkId`. `getNetworksData` returns every network configured for your project, across all chains — filter it to the wallet's `chain` so the picker only offers networks the wallet can actually switch to.

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

    async function renderNetworkPicker(
      select: HTMLSelectElement,
      walletAccount: WalletAccount,
    ) {
      const { networkData } = await getActiveNetworkData({ walletAccount });
      // getNetworksData spans every configured chain; a wallet can only switch
      // within its own chain, so keep only the networks on the wallet's chain.
      const networks = getNetworksData().filter(
        (network) => network.chain === walletAccount.chain,
      );

      select.replaceChildren();
      for (const network of networks) {
        const option = document.createElement('option');
        option.value = network.networkId;
        option.textContent = network.displayName;
        option.selected = network.networkId === networkData?.networkId;
        select.append(option);
      }

      select.addEventListener('change', async () => {
        await switchActiveNetwork({ networkId: select.value, walletAccount });
      });
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import {
      getNetworksData,
      type WalletAccount,
    } from '@dynamic-labs-sdk/client';
    import {
      useGetActiveNetworkData,
      useSwitchActiveNetwork,
    } from '@dynamic-labs-sdk/react-hooks';

    function NetworkPicker({ walletAccount }: { walletAccount: WalletAccount }) {
      const { data } = useGetActiveNetworkData({ walletAccount });
      const { mutateAsync: switchNetwork, isPending } = useSwitchActiveNetwork();
      // Keep only networks on the wallet's own chain — the only ones it can switch to.
      const networks = getNetworksData().filter(
        (network) => network.chain === walletAccount.chain,
      );

      return (
        <select
          value={data?.networkData?.networkId ?? ''}
          disabled={isPending}
          onChange={(event) =>
            switchNetwork({ networkId: event.target.value, walletAccount })
          }
        >
          {networks.map((network) => (
            <option key={network.networkId} value={network.networkId}>
              {network.displayName}
            </option>
          ))}
        </select>
      );
    }
    ```

    The active-network query refetches on `networkChanged`, so the picker reflects switches made anywhere — including from inside the wallet.
  </Tab>
</Tabs>

## Validating before an action

Before a transaction that must run on a specific network, check the active network and switch if needed. Some wallets don't allow programmatic switching — `isProgrammaticNetworkSwitchAvailable` tells you whether to switch for the user or ask them to switch in their wallet.

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

    // Ensure the wallet is on `requiredNetworkId`; returns whether it's safe to proceed.
    async function ensureNetwork(
      walletAccount: WalletAccount,
      requiredNetworkId: string,
    ): Promise<boolean> {
      const { networkData } = await getActiveNetworkData({ walletAccount });
      if (networkData?.networkId === requiredNetworkId) return true;

      if (isProgrammaticNetworkSwitchAvailable({ walletAccount })) {
        await switchActiveNetwork({ networkId: requiredNetworkId, walletAccount });
        return true;
      }

      // promptManualSwitch is your implementation — tell the user to switch in their wallet.
      promptManualSwitch(requiredNetworkId);
      return false;
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import {
      getActiveNetworkData,
      isProgrammaticNetworkSwitchAvailable,
    } from '@dynamic-labs-sdk/client';
    import type { WalletAccount } from '@dynamic-labs-sdk/client';
    import { useSwitchActiveNetwork } from '@dynamic-labs-sdk/react-hooks';

    function useEnsureNetwork(walletAccount: WalletAccount) {
      const { mutateAsync: switchNetwork } = useSwitchActiveNetwork();

      return async (requiredNetworkId: string) => {
        const { networkData } = await getActiveNetworkData({ walletAccount });
        if (networkData?.networkId === requiredNetworkId) return true;

        if (!isProgrammaticNetworkSwitchAvailable({ walletAccount })) return false;

        await switchNetwork({ networkId: requiredNetworkId, walletAccount });
        return true;
      };
    }
    ```
  </Tab>
</Tabs>

<Tip>
  Call your network check right before sending — not just on page load. A user can switch networks in their wallet at any time, so validate at the moment the network actually matters.
</Tip>

## Handling errors

| Situation                                            | What to do                                                                                                        |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `isProgrammaticNetworkSwitchAvailable` is `false`    | Show the target network's `displayName` and ask the user to switch in their wallet, then re-check.                |
| User rejects the switch prompt (`UserRejectedError`) | Keep them on the current network and don't proceed with the action that required the switch.                      |
| Target network not in `getNetworksData`              | It isn't enabled for your project — enable it in the dashboard rather than hardcoding it.                         |
| `networkData` is `undefined`                         | The wallet's current chain isn't among your configured networks; treat it as "wrong network" and prompt a switch. |

## See also

* [Connected wallets management](/docs/javascript/building-ui/connected-wallets-management) — the wallet you're switching networks for
* [Transaction confirmation & simulation](/docs/javascript/building-ui/transaction-confirmation) — validate the network right before sending
* [Token balances & display](/docs/javascript/building-ui/token-balances-display) — balances are per network
