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

# Base Account Connection Guide

> Connect Base Account on web through the keys.coinbase.com popup or QR flow, and on React Native through the Mobile Wallet Protocol.

Use the JavaScript SDK to support [Base Account](https://docs.base.org/identity/smart-wallet/introduction/sw-quickstart) through one of these routes:

* A popup or QR code at `keys.coinbase.com` on web, surfacing both Coinbase Smart Wallet (passkey-backed ERC-4337) and Coinbase Wallet (EOA).
* A Mobile Wallet Protocol deep link into the Coinbase Wallet app on React Native, surfacing Coinbase Smart Wallet.

The Coinbase Wallet browser extension is handled separately by the standard EIP-6963 and window-injected extensions. See [Base Account extension](/docs/javascript/reference/evm/adding-evm-extensions#base-account-extension) for the full extension options.

## Prerequisites

* [Create](/docs/javascript/reference/client/create-dynamic-client) and [initialize](/docs/javascript/reference/client/initialize-dynamic-client) a Dynamic client.
* Enable EVM in the [Dynamic developer console](https://console.dynamic.xyz/dashboard/chains-and-networks#evm).
* Install `@dynamic-labs-sdk/evm`.
* On React Native, complete [React Native setup](/docs/javascript/react-native/setup) first.

## Add the extension

```typescript theme={"system"}
import { addEvmExtension } from '@dynamic-labs-sdk/evm';
import { addBaseAccountEvmExtension } from '@dynamic-labs-sdk/evm/base-account';

addEvmExtension();
addBaseAccountEvmExtension();
```

Keep `addEvmExtension` so the Coinbase Wallet browser extension is still discovered through EIP-6963.

Pass `preference.options` to control which Base Account flavors appear in the web popup (`'all'` by default). On React Native the preference is ignored: Mobile Wallet Protocol always targets Coinbase Smart Wallet.

## Connect a wallet

Base Account registers as a wallet SDK provider, so connect through the generic wallet provider lifecycle: find its provider key with `getAvailableWalletProvidersData`, then call `connectAndVerifyWithWalletProvider`.

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

const baseAccountProvider = getAvailableWalletProvidersData(
  dynamicClient,
).find((provider) => provider.metadata.displayName === 'Base Account');

if (baseAccountProvider) {
  const walletAccount = await connectAndVerifyWithWalletProvider({
    walletProviderKey: baseAccountProvider.key,
  });

  console.log(walletAccount.address);
}
```

On web this opens the `keys.coinbase.com` popup or a QR code. On React Native it deep-links the user into the Coinbase Wallet app and returns to your app through your deep link scheme.

## React Native

The native build of `@dynamic-labs-sdk/evm/base-account` talks to the Coinbase Wallet app through [@mobile-wallet-protocol/client](https://www.npmjs.com/package/@mobile-wallet-protocol/client). Two things are required that web does not need: the Mobile Wallet Protocol packages installed, and `metadata.nativeLink` on the client.

This section assumes the app from the [React Native quickstart](/docs/javascript/reference/react-native-quickstart).

### Install the peer dependencies

`@mobile-wallet-protocol/client` is an optional peer of `@dynamic-labs-sdk/evm`, so install it (and its own Expo peers) in your app:

```bash theme={"system"}
npm install @mobile-wallet-protocol/client expo expo-web-browser @react-native-async-storage/async-storage
```

If it is missing when the extension connects, the SDK throws `BaseAccountMissingMobileWalletProtocolError`.

<Note>
  `@mobile-wallet-protocol/client` depends on Expo modules (`expo`, `expo-web-browser`). On bare React Native you must install Expo modules before using Base Account. See [Setup on Bare React Native](/docs/javascript/react-native/bare-react-native).
</Note>

### Configure the native link

The Coinbase Wallet app returns the user to your app through your app's custom URL scheme after it approves a request. Set `metadata.nativeLink` on the client to the same scheme you registered in `app.json`, `Info.plist`, and `AndroidManifest.xml`:

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

const dynamicClient = createDynamicClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  metadata: {
    name: 'Your App',
    nativeLink: 'myapp://',
  },
});
```

Without `nativeLink`, `addBaseAccountEvmExtension` throws `BaseAccountMissingNativeLinkError` at registration time.

### Handle the deep link return with expo-router

On Expo Router apps, the Mobile Wallet Protocol callback URL (`myapp://mobile-wallet-protocol`) arrives as a deep link. Expo Router resolves unknown URLs against your route table, so intercept it in `+native-intent.ts` before it reaches the unmatched-route screen:

```tsx +native-intent.ts theme={"system"}
const MOBILE_WALLET_PROTOCOL_PATH = 'mobile-wallet-protocol';

export function redirectSystemPath({ path }: { path: string }): string {
  if (path.startsWith(`/${MOBILE_WALLET_PROTOCOL_PATH}`)) {
    return '';
  }
  try {
    const url = new URL(path);
    const isProtocolHost = url.hostname === MOBILE_WALLET_PROTOCOL_PATH;
    const isProtocolPath =
      url.pathname.replace(/^\/+/, '') === MOBILE_WALLET_PROTOCOL_PATH;
    if (isProtocolHost || isProtocolPath) {
      return '';
    }
  } catch {
    // Not an absolute URL, so this is a normal in-app route.
  }
  return path;
}
```

Returning `''` tells Expo Router to stay on the current screen. The hostname check covers the iOS callback form where the scheme yields a double slash (`myapp:////mobile-wallet-protocol`), which parses the path into the hostname.

## Common pitfalls

### Connection opens but never returns to the app

The scheme in `metadata.nativeLink` must match the scheme registered in `app.json` (`"scheme": "myapp"`) or in the native `Info.plist` / `AndroidManifest.xml`. A mismatch leaves the user in the Coinbase Wallet app after approval.

### The unmatched-route screen appears after approving in Coinbase Wallet

On Expo Router, add the `redirectSystemPath` guard shown above. Without it, the `mobile-wallet-protocol` callback URL is treated as an app route.

### The app bundle cannot resolve the Mobile Wallet Protocol peer

The optional peer is not installed in the app (or Metro's bundle predates the install). Install `@mobile-wallet-protocol/client` and rebuild the bundle.
