Skip to main content
Get started with Dynamic’s React Native SDK to add embedded wallets, multi-chain support, and flexible authentication (email, social login, passkeys) to your mobile app in just a few lines.
Before you start: You’ll need Node.js 18+ and a Dynamic environment ID from the Dynamic dashboard.
Add the Dynamic docs MCP to your AI editor first — your agent can then query the docs directly. Instructions are on the Welcome page.
Copy this prompt into your LLM (e.g. Claude, ChatGPT, Cursor) to implement Dynamic in your React Native app.
# React Native SDK Quickstart

## Purpose and Usage

This document provides structured quickstart information for the Dynamic React Native SDK. It is designed to be consumed by LLMs to generate accurate installation commands and code examples based on user requirements.

> **Architecture note:** The React Native SDK uses a client-based architecture with extensions — NOT the provider-based architecture of the React SDK. Do NOT use `DynamicContextProvider`, `DynamicWidget`, or any other React SDK patterns here. They are different SDKs.

**How to use this document:**

**BEFORE WRITING ANY CODE**, ask the user which path they want:

> "Would you like a **Quick start** (Expo managed workflow + EVM, zero configuration — recommended if you're just getting started) or a **Custom setup** (choose your workflow, chains, passkeys, and account abstraction)?"

Do not proceed until the user has answered. Do not assume a path.

---

## Quick Start Path

> Use this path when the user chooses Quick start. Execute every step in order. Do not skip steps. Do not ask configuration questions.

**Stack:** Expo managed workflow + npm + EVM only + no passkeys + no ZeroDev

### Step 1 — Prerequisites

Tell the user:
- Node.js 18+ is required
- A Dynamic environment ID is required — get one at https://app.dynamic.xyz/dashboard/developer
- **This SDK is NOT compatible with Expo Go.** You must use a development build or EAS Build. If the user is using Expo Go, stop and inform them before proceeding.
- Test on a real device early — some features (passkeys, global wallets) do not work in simulators

Ask the user for their environment ID before proceeding.

### Step 2 — Scaffold the project

```bash
pnpm dlx create-expo-app my-app --template blank-typescript
cd my-app
```

### Step 3 — Install

Install all required packages explicitly. Missing peer dependencies cause runtime errors, not build errors — install all of them.

```bash
pnpm add @dynamic-labs/client @dynamic-labs/react-native-extension @dynamic-labs/viem-extension @dynamic-labs/react-hooks
```

> **pnpm build scripts:** pnpm v10 suppresses build scripts by default. Add the following to your `package.json` before installing to avoid native module issues:
> ```json
> "pnpm": { "onlyBuiltDependencies": ["@react-native-community/cli", "react-native", "esbuild"] }
> ```

### Step 4 — Prebuild (required — native modules)

The SDK relies on native modules (`react-native-webview`, `expo-secure-store`). You must rebuild the native layer after installing.

```bash
npx expo prebuild
```

> **CocoaPods UTF-8 error (macOS):** If `pod install` fails with `Unicode Normalization not appropriate for ASCII-8BIT`, run the following and retry:
> ```bash
> export LANG=en_US.UTF-8
> npx expo prebuild
> ```

Then run your app:
```bash
LANG=en_US.UTF-8 npx expo run:ios
# or
LANG=en_US.UTF-8 npx expo run:android
```

> **Warning:** Do not use `npx expo start` with Expo Go after this step — it will not work. Always use `expo run:ios` / `expo run:android` or a development build.

### Step 5 — Initialize the client

Create a `client.ts` file at the project root:

```typescript
import { createClient } from '@dynamic-labs/client';
import { ReactNativeExtension } from '@dynamic-labs/react-native-extension';
import { ViemExtension } from '@dynamic-labs/viem-extension';

export const dynamicClient = createClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  appLogoUrl: 'https://demo.dynamic.xyz/favicon-32x32.png',
  appName: 'My App',
  appOrigin: 'http://localhost:8081', // Required — use http://localhost:8081 for local Expo development
})
  .extend(ReactNativeExtension())
  .extend(ViemExtension());
```

> **`appOrigin` is required.** This must be set to your app's domain. It is used for MPC wallet operations and passkey configuration. The quickstart will not work without it.

### Step 6 — Add the WebView to your app

Open `App.tsx` (or `App.js` if your project uses JavaScript) and replace the contents:

```typescript
// App.tsx
import { SafeAreaView, Text } from 'react-native';
import { dynamicClient } from './client';

export default function App() {
  return (
    <>
      <dynamicClient.reactNative.WebView />
      <SafeAreaView>
        <Text>Hello from Dynamic!</Text>
      </SafeAreaView>
    </>
  );
}
```

### Step 7 — Read wallet state in a component

Use `useReactiveClient` from `@dynamic-labs/react-hooks` to reactively access client state in React components:

```typescript
import { useReactiveClient } from '@dynamic-labs/react-hooks';
import { dynamicClient } from './client';

export function WalletInfo() {
  const { wallets } = useReactiveClient(dynamicClient);
  const wallet = wallets[0];

  if (!wallet) return null;

  return <Text>Address: {wallet.address}</Text>;
}
```

### Step 8 — Dashboard configuration checklist

Before testing, verify these settings in your Dynamic dashboard at https://app.dynamic.xyz:

1. **Chains enabled** — go to **Chains & Networks** and enable EVM
2. **Embedded wallets enabled** — go to **Wallets** and enable embedded wallets
3. **Login method enabled** — go to **Sign-in Methods** and enable at least one (e.g. email OTP)
4. **CORS origin allowlisted** — go to **Security → Allowed Origins** and add your app's origin (e.g. `http://localhost:8081`)
5. **Deeplink URL registered** — go to **Security → Deeplink URLs** and add your app's deeplink scheme (required for social login and OAuth flows). See https://docs.dynamic.xyz/react-native/reference/deeplink-urls for setup instructions.

---

## Custom Setup Path

> Use this path when the user chooses Custom setup. Ask ALL questions below before generating any code.

**Questions to ask the user:**

1. Which workflow are you using? (Expo managed, EAS Build, bare React Native)
2. Which package manager do you prefer? (npm, yarn, pnpm, bun, expo)
3. Which chains do you want to support? (EVM, SVM, Sui — one or more)
4. Do you want to enable passkeys?
5. If EVM: do you want to enable Account Abstraction (ZeroDev)?

**Only after receiving answers**, use the sections below to generate the correct setup.

### Package Manager Commands
- `npm`: `npm i`
- `yarn`: `yarn add`
- `pnpm`: `pnpm add`
- `bun`: `bun add`
- `expo`: `npx expo install`

### Package Mapping

Always install all of the following explicitly — missing peer dependencies cause runtime errors, not build errors.

- Core (always required): `@dynamic-labs/client`
- React Native extension (always required): `@dynamic-labs/react-native-extension`
- EVM: `@dynamic-labs/viem-extension`
- SVM: `@dynamic-labs/solana-extension`
- Sui: `@dynamic-labs/sui-extension`
- ZeroDev (EVM only): `@dynamic-labs/zerodev-extension` + `events`

### Prebuild / Native Linking

Always required after install — the SDK relies on native modules.

- **Expo managed**: `npx expo prebuild``npx expo run:ios` or `npx expo run:android`
- **EAS Build**: native modules linked automatically — run `eas build --profile <your-profile> --platform all`
- **Bare React Native**: `cd ios && pod install && cd ..` → rebuild with Xcode or `npx react-native run-ios` / `npx react-native run-android`

> **Warning:** This SDK is NOT compatible with Expo Go. Always use a development build or EAS Build.

### Extension Mapping
- EVM → `ViemExtension` from `@dynamic-labs/viem-extension`
- SVM → `SolanaExtension` from `@dynamic-labs/solana-extension`
- Sui → `SuiExtension` from `@dynamic-labs/sui-extension`
- ZeroDev → `ZeroDevExtension` from `@dynamic-labs/zerodev-extension`

### Client Initialization

```typescript
import { createClient } from '@dynamic-labs/client';
import { ReactNativeExtension } from '@dynamic-labs/react-native-extension';

export const dynamicClient = createClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  appLogoUrl: 'https://demo.dynamic.xyz/favicon-32x32.png',
  appName: 'My App',
  appOrigin: 'https://YOUR-DOMAIN.com', // Required
})
  .extend(ReactNativeExtension({PASSKEY_CONFIG}))
  .extend({CHAIN_EXTENSIONS});
```

**Passkeys enabled:**
```typescript
ReactNativeExtension({ appOrigin: 'https://YOUR-DOMAIN.com' })
```

**Passkeys disabled:**
```typescript
ReactNativeExtension()
```

### WebView (required)

Always include `<dynamicClient.reactNative.WebView />` at the root of your component tree. Without it, the SDK's UI and auth flows will not function.

### Reactive State in Components

Use `useReactiveClient` from `@dynamic-labs/react-hooks` to access client state reactively in React components. Do NOT use React SDK hooks (`useDynamicContext`, etc.) — they do not exist in this SDK.

```typescript
import { useReactiveClient } from '@dynamic-labs/react-hooks';
import { dynamicClient } from './client';

const { wallets } = useReactiveClient(dynamicClient);
```

### TODOs for custom config

**When passkeys are enabled:**
```typescript
// TODO: Complete passkey setup — https://docs.dynamic.xyz/react-native/reference/setup-passkey
```

**When ZeroDev is enabled:**
```typescript
// TODO: Check for file resolution error fix — https://docs.dynamic.xyz/react-native/reference/wallets/account-abstraction#resolve-file-resolution-error-optional
```

**When social login is needed:**
```typescript
// TODO: Configure deeplink URLs — https://docs.dynamic.xyz/react-native/reference/deeplink-urls
```

### Valid Chain Combinations
- Any single chain or combination of EVM, SVM, and Sui is valid
- ZeroDev only applies when EVM is selected
- At least one chain must be selected

### Documentation
All docs for this SDK: https://docs.dynamic.xyz (paths starting with `/react-native/`)
Environment ID: https://app.dynamic.xyz/dashboard/developer/api

---

## Critical Reference

| Correct | Incorrect | Notes |
|---|---|---|
| `createClient().extend(ReactNativeExtension())` | `DynamicContextProvider` / `DynamicWidget` | React Native uses client + extensions, not providers |
| `useReactiveClient(dynamicClient)` | `useDynamicContext()` | React SDK hooks do not exist in this SDK |
| `<dynamicClient.reactNative.WebView />` | Omitting WebView | Required in component tree — auth flows will silently fail without it |
| `appOrigin: 'https://your-domain.com'` | Omitting `appOrigin` | Required field — wallet operations will fail without it |
| `npx expo run:ios` / `npx expo run:android` | `npx expo start` with Expo Go | Expo Go does not support custom native modules |
| Install all packages explicitly | Rely on transitive deps | Missing peer deps cause runtime errors, not build errors |

---

## Troubleshooting

### 1 — App crashes immediately after install
Native modules were not linked. Run `npx expo prebuild` and rebuild with `npx expo run:ios` or `npx expo run:android`. Do not use Expo Go.

### 2 — Auth flow does nothing / WebView not showing
`<dynamicClient.reactNative.WebView />` is missing from the component tree. Add it at the root level of your app.

### 3 — Wallet creation fails or returns no wallet
Check the dashboard: embedded wallets must be enabled under **Wallets**, chains must be enabled under **Chains & Networks**, and the app origin must be allowlisted under **Security → Allowed Origins**.

### 4 — Social login / OAuth redirects fail
Deeplink URLs must be registered in the Dynamic dashboard under **Security → Deeplink URLs**. Your app URL scheme must also be configured in `app.json`. See https://docs.dynamic.xyz/react-native/reference/deeplink-urls.

### 5 — Passkey errors
Passkeys require additional native setup beyond installing the package and setting `appOrigin`. Follow the full passkey setup guide: https://docs.dynamic.xyz/react-native/reference/setup-passkey. Passkeys also do not work in simulators — test on a real device.

### 6 — Wrong hook or import errors
Do not use React SDK imports (`@dynamic-labs/sdk-react-core`, `useDynamicContext`, etc.) in a React Native project. The React Native SDK is a separate package with a different API surface. Some docs pages under the React Native section may show React SDK patterns for certain chains — those examples are not correct for the React Native client-based architecture.

If the issue persists, check https://docs.dynamic.xyz/react-native/reference/troubleshooting and https://docs.dynamic.xyz/overview/troubleshooting/general.