> For the complete documentation index, see [llms.txt](/llms.txt).

# React Native SDK migration guide

This page is the **only** React Native migration guide you need. It consolidates all prior version guides (v3 through v8) into one path to **v9** (`@web3auth/react-native-sdk@^9`).

v9 is a **hooks-only** API: wrap your app in `Web3AuthProvider` and use hooks such as `useWeb3AuthConnect` and `useWeb3AuthDisconnect`. The imperative `new Web3Auth(...)` / `.init()` / `.login()` pattern is removed.

Follow the steps below and mirror the official v9 examples in [web3auth-react-native-examples](https://github.com/Web3Auth/web3auth-react-native-examples) (for example, [rn-bare-quick-start](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start) and [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example)). Do not use the [SDK repository README](https://github.com/Web3Auth/web3auth-react-native-sdk); it still documents the legacy class API.

---

## Agent prompt

### Setup (recommended)

Install the Web3Auth skill and enable the Web3Auth MCP server in your editor so the agent can look up MetaMask Embedded Wallets correctly:

```bash
npx skills add web3auth/skill

```

<details>
<summary>**Full agent prompt**: expand, then use Copy on the code block</summary>

React Native SDK v9 migration prompt

```text
ROLE
You are a code-migration agent. Your job is to upgrade the open repository to @web3auth/react-native-sdk v9 (MetaMask Embedded Wallets). Stay inside the repo. Do not run package-manager installs, git commands, or shell side effects unless the user explicitly approves them; only propose them.

CONTEXT
v9 is a hooks-first API. The legacy imperative pattern (new Web3Auth(...), .init(), .login(), privateKeyProvider, loginConfig, useCoreKitKey, useSFAKey, OPENLOGIN_NETWORK, LOGIN_PROVIDER, manual globals.js, manual Metro polyfills, @web3auth/ethereum-provider, @web3auth/solana-provider, SolanaWallet) is removed.

KNOWLEDGE SOURCES (do not guess Web3Auth APIs from memory)
- Use the "web3auth" skill and Web3Auth MCP server to learn about MetaMask Embedded Wallets and confirm package names, hooks, and configuration. If the skill is missing, ask the user to run: npx skills add web3auth/skill
- Use this migration guide for legacy SDK → v9 edits (any version before v9): https://metamask-docs-git-docs-agent-wallet-s-66054a-consensys-ddffed67.vercel.app/embedded-wallets/migration-guides/react-native/
- If neither is available, use the inline PHASE 2 rules below.

PHASE 1: DISCOVERY (read-only)
1. List files at repo root. Detect bare React Native vs Expo by checking for "expo" in package.json dependencies or an app.json with "expo".
2. Read these files if they exist: package.json, index.js, index.ts, App.tsx, App.js, metro.config.js, metro.config.ts, babel.config.js, babel.config.ts, globals.js, globals.ts, web3authConfig.ts, web3authConfig.js, and any file that imports from "@web3auth/react-native-sdk" or "@web3auth/ethereum-provider" or "@web3auth/solana-provider".
3. Classify the current SDK version using these signals:
   - Has Web3AuthProvider + useWeb3Auth + AUTH_CONNECTION → already v9, only run verification.
   - new Web3Auth + privateKeyProvider + WEB3AUTH_NETWORK → v8.
   - new Web3Auth + OPENLOGIN_NETWORK → v7 or earlier.
   - new Web3Auth with only two constructor args → v3 or earlier.
4. Print a short discovery report (workflow, detected version, files that will change). Then ask for confirmation before editing if any rule below would delete or rename files.

PHASE 2: EDITS (in this exact order)

A. package.json
   - Set "@web3auth/react-native-sdk" to ^9.0.0.
   - Add devDependency "@babel/plugin-transform-export-namespace-from" (latest 7.x) if not already present (matches public examples).
   - Remove legacy Web3Auth-only packages when nothing else needs them: react-native-get-random-values, @web3auth/ethereum-provider, @web3auth/solana-provider, @web3auth/base.
   - Do NOT add react-native-quick-crypto for v9; public examples do not import it. withWeb3Auth handles Metro polyfills.
   - Do NOT add manual polyfill packages (crypto-browserify, empty-module, readable-stream, buffer) for Web3Auth. Remove legacy globals.js / manual Metro extraNodeModules instead.
   - If the app uses ethers v6, install ethers and @ethersproject/shims (public examples import shims before ethers).
   - Expo only: ensure "main": "index.ts".
   - Do NOT pin to a specific patch version unless one is already pinned.

B. Entry file (index.js for bare, index.ts for Expo)
   - The FIRST line must be: import '@web3auth/react-native-sdk/setup'
   - Remove imports of './globals', 'react-native-get-random-values', or other manual polyfill shims.
   - Expo (match rn-expo-example): second line can be import '@ethersproject/shims' when using ethers; then registerRootComponent(App).
   - Bare: keep setup in index.js; import '@ethersproject/shims' in App.tsx (before ethers) when using ethers.
   - Bare RN keeps AppRegistry.registerComponent(...).

C. metro.config.js
   - Replace manual polyfill blocks with:
     const { getDefaultConfig } = require('@react-native/metro-config') // bare
     // OR: const { getDefaultConfig } = require('expo/metro-config') // expo
     const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')
     const config = getDefaultConfig(__dirname)
     module.exports = withWeb3Auth(config)
   - Delete globals.js, react-native-quick-crypto resolveRequest hacks, and hand-rolled extraNodeModules for crypto/stream.

D. babel.config.js
   - Match public examples: add '@babel/plugin-transform-export-namespace-from' to plugins (bare and Expo).

E. web3authConfig.ts (create if missing)
   - export default a value typed as Web3AuthContextConfig from '@web3auth/react-native-sdk'.
   - Required: clientId, redirectUrl ('scheme://auth'), network (WEB3AUTH_NETWORK.*).
   - chains / defaultChainId are OPTIONAL when chains are configured on the Embedded Wallets dashboard; add them locally for custom RPCs, Solana, or multi-chain (see rn-bare-solana-example).
   - Do NOT include privateKeyProvider, loginConfig, useCoreKitKey, or useSFAKey.
   - Preserve clientId, RPCs, redirect scheme, and whitelabel values from existing code.

F. App root (hooks only)
   - Delete module-level "const web3auth = new Web3Auth(...)" and any useEffect that calls web3auth.init().
   - Wrap the tree in <Web3AuthProvider webBrowser={WebBrowser} storage={Storage} config={web3AuthConfig}>...</Web3AuthProvider>
   - Bare RN: import * as WebBrowser from '@toruslabs/react-native-web-browser'; EncryptedStorage from 'react-native-encrypted-storage'.
   - Expo: import * as WebBrowser from 'expo-web-browser'; import * as SecureStore from 'expo-secure-store'.

G. Auth screens / hooks
   - Replace LOGIN_PROVIDER.X with AUTH_CONNECTION.X (GOOGLE, FACEBOOK, APPLE, DISCORD, TWITTER, GITHUB, EMAIL_PASSWORDLESS, SMS_PASSWORDLESS). LOGIN_PROVIDER.JWT → AUTH_CONNECTION.CUSTOM with authConnectionId set to the dashboard Connection ID.
   - Replace web3auth.login({ loginProvider, extraLoginOptions }) with useWeb3AuthConnect().connectTo({ authConnection, extraLoginOptions, ... }).
   - Custom JWT: pass idToken as a TOP-LEVEL field on connectTo (not inside extraLoginOptions). Move loginConfig[key].verifierSubIdentifier → groupedAuthConnectionId.
   - Replace web3auth.logout() with useWeb3AuthDisconnect().disconnect().
   - Replace web3auth.userInfo() with useWeb3AuthUser().userInfo.
   - Replace web3auth.connected and web3auth.provider with useWeb3Auth() (isConnected, isInitializing, provider, web3Auth).

H. Blockchain code
   - EVM with ethers v6: import '@ethersproject/shims' before ethers; const { provider } = useWeb3Auth(); new ethers.BrowserProvider(provider!).
   - Solana: drop SolanaWallet / @web3auth/solana-provider. Use const { web3Auth } = useWeb3Auth(); const signer = web3Auth?.signer as TransactionSigner; address = String(signer.address). See rn-bare-solana-example.

I. Wallet Services
   - launchWalletServices(chainConfig) → useWalletUI().showWalletUI().
   - request(chainConfig, method, params) → useSignatureRequest().request(method, params).
   - Identity JWT fetches → useIdentityToken().getIdentityToken().
   - MFA → useEnableMFA().enableMFA() and useManageMFA().manageMFA().

J. Misc
   - Any redirect URL ending in "://openlogin" becomes "://auth". Remind the user to update the dashboard Allowed Origins.
   - Delete globals.js / globals.ts.
   - Rename whiteLabel.name → whiteLabel.appName, whiteLabel.dark: boolean → whiteLabel.mode: 'light' | 'dark' | 'auto'.

CONSTRAINTS
- Do not invent dependency versions. Use ^9.0.0 for the SDK and current ^7.x for the Babel plugin; ask the user for any other version you are unsure about.
- Do not modify CI, lockfiles, or unrelated code.
- Do not run installers, builds, prebuild, or git commands. Print the commands and let the user run them.
- Preserve every existing user-supplied value (clientId, RPCs, scheme, whitelabel theme).

PHASE 3: REPORT
At the end output, in order:
1. A unified diff for every changed file.
2. A list of files to create and files to delete.
3. The exact commands the user should run (install, uninstall, pod install or expo prebuild).
4. A pass/fail line per checklist item:
   - SDK at ^9.0.0
   - Babel plugin present
   - Entry file first line is the setup import
   - globals.js deleted
   - metro.config.js uses withWeb3Auth
   - web3authConfig.ts exports Web3AuthContextConfig (chains optional if set on dashboard) and no privateKeyProvider
   - redirectUrl uses ://auth
   - App wrapped in Web3AuthProvider, no useEffect init
   - All logins use connectTo + AUTH_CONNECTION (no LOGIN_PROVIDER references)
   - Custom JWT uses top-level idToken + authConnectionId
   - EVM uses useWeb3Auth().provider; Solana uses web3Auth.signer
   - Expo only: "main": "index.ts"
5. A short note listing manual steps the user must do (dashboard update, ./auth deep link, pod install, expo prebuild).

```


</details>

The mapping tables, code samples, and checklist below are the detailed reference for this migration.

---

## Version detection

Inspect the codebase and classify the starting point:

| Signal in code                                               | Likely version                               |
| ------------------------------------------------------------ | -------------------------------------------- |
| `Web3AuthProvider`, `useWeb3Auth`, `AUTH_CONNECTION`         | Already v9, verify checklist only            |
| `new Web3Auth`, `privateKeyProvider`, `WEB3AUTH_NETWORK`     | v8                                           |
| `new Web3Auth`, `OPENLOGIN_NETWORK`, no `privateKeyProvider` | v7 or earlier                                |
| `new Web3Auth(WebBrowser)`, **two** constructor args         | v3 or earlier                                |
| `globals.js` + `crypto-browserify` in Metro                  | v3-v6 legacy polyfills                       |
| `react-native-quick-crypto` in Metro `resolveRequest`        | v6 (remove manual wiring; do not add for v9) |
| `whiteLabel.name` or `whiteLabel.dark`                       | v4 or earlier whitelabel                     |
| `loginConfig`, `LOGIN_PROVIDER.JWT`, `useCoreKitKey`         | v8 custom auth (maps to v9 `connectTo`)      |

You can jump from any row directly to v9; you do not need intermediate upgrades.

---

## API mapping (legacy → v9)

| Legacy (v3-v8)                                                | v9 replacement                                                                     |         |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------- |
| `new Web3Auth(browser, storage, options)` + `init()`          | `<Web3AuthProvider webBrowser storage config>` (auto-init)                         |         |
| `new Web3Auth(browser, options)` (no storage)                 | Add storage + `Web3AuthProvider` (storage required since v4)                       |         |
| `OPENLOGIN_NETWORK.*`                                         | `WEB3AUTH_NETWORK.*`                                                               |         |
| `LOGIN_PROVIDER.*`                                            | `AUTH_CONNECTION.*`                                                                |         |
| `web3auth.login({ loginProvider, extraLoginOptions })`        | `connectTo({ authConnection, extraLoginOptions, ... })` via `useWeb3AuthConnect()` |         |
| `web3auth.logout()`                                           | `disconnect()` via `useWeb3AuthDisconnect()`                                       |         |
| `web3auth.userInfo()`                                         | `userInfo` from `useWeb3AuthUser()`                                                |         |
| `web3auth.privKey` / `web3auth.ed25519Key`                    | `provider` / `web3Auth.signer` (no direct key getters)                             |         |
| `web3auth.connected` + `web3auth.provider`                    | `isConnected` + `provider` from `useWeb3Auth()`                                    |         |
| `ethereumPrivateKeyProvider` / `SolanaPrivateKeyProvider`     | Optional `chains: [...]` in `web3AuthOptions` (or dashboard chain config)          |         |
| `loginConfig` + `verifier`                                    | Dashboard connection + `authConnectionId` in `connectTo`                           |         |
| `verifierSubIdentifier`                                       | `groupedAuthConnectionId` in `connectTo`                                           |         |
| `LOGIN_PROVIDER.JWT` + `id_token` in `extraLoginOptions`      | `AUTH_CONNECTION.CUSTOM` + `authConnectionId` + top-level `idToken`                |         |
| `useCoreKitKey` / `useSFAKey`                                 | **Removed**, delete                                                                |         |
| `launchWalletServices(chainConfig)`                           | `showWalletUI()` via `useWalletUI()`                                               |         |
| `request(chainConfig, method, params)`                        | `request(method, params)` via `useSignatureRequest()`                              |         |
| `SolanaWallet` / `@web3auth/solana-provider`                  | `web3Auth.signer` as `TransactionSigner`                                           |         |
| `scheme://openlogin`                                          | `scheme://auth`                                                                    |         |
| `whiteLabel.name`                                             | `whiteLabel.appName`                                                               |         |
| `whiteLabel.dark: boolean`                                    | `whiteLabel.mode: 'light' \| 'dark'                                                | 'auto'` |
| `import './globals'`, `react-native-get-random-values`        | `import '@web3auth/react-native-sdk/setup'` (first line)                           |         |
| Manual Metro `extraNodeModules` / `react-native-quick-crypto` | `withWeb3Auth(getDefaultConfig(__dirname))`                                        |         |

### `LOGIN_PROVIDER` → `AUTH_CONNECTION`

| Legacy                              | v9                                   |
| ----------------------------------- | ------------------------------------ |
| `LOGIN_PROVIDER.GOOGLE`             | `AUTH_CONNECTION.GOOGLE`             |
| `LOGIN_PROVIDER.FACEBOOK`           | `AUTH_CONNECTION.FACEBOOK`           |
| `LOGIN_PROVIDER.APPLE`              | `AUTH_CONNECTION.APPLE`              |
| `LOGIN_PROVIDER.DISCORD`            | `AUTH_CONNECTION.DISCORD`            |
| `LOGIN_PROVIDER.TWITTER`            | `AUTH_CONNECTION.TWITTER`            |
| `LOGIN_PROVIDER.GITHUB`             | `AUTH_CONNECTION.GITHUB`             |
| `LOGIN_PROVIDER.EMAIL_PASSWORDLESS` | `AUTH_CONNECTION.EMAIL_PASSWORDLESS` |
| `LOGIN_PROVIDER.SMS_PASSWORDLESS`   | `AUTH_CONNECTION.SMS_PASSWORDLESS`   |
| `LOGIN_PROVIDER.JWT`                | `AUTH_CONNECTION.CUSTOM`             |

---

## Migration workflow

Execute these steps in order. Skip steps already satisfied in v9 projects.

### Step 1, Dependencies

**Install**

**npm**

```bash
npm install @web3auth/react-native-sdk@^9.0.0
npm install --save-dev @babel/plugin-transform-export-namespace-from

```

**Yarn**

```bash
yarn add @web3auth/react-native-sdk@^9.0.0
yarn add --dev @babel/plugin-transform-export-namespace-from

```

**pnpm**

```bash
pnpm add @web3auth/react-native-sdk@^9.0.0
pnpm add --save-dev @babel/plugin-transform-export-namespace-from

```

**Bun**

```bash
bun add @web3auth/react-native-sdk@^9.0.0
bun add --dev @babel/plugin-transform-export-namespace-from

```

**Bare React Native, keep or install**

**npm**

```bash
npm install @toruslabs/react-native-web-browser react-native-encrypted-storage

```

**Yarn**

```bash
yarn add @toruslabs/react-native-web-browser react-native-encrypted-storage

```

**pnpm**

```bash
pnpm add @toruslabs/react-native-web-browser react-native-encrypted-storage

```

**Bun**

```bash
bun add @toruslabs/react-native-web-browser react-native-encrypted-storage

```

**Expo, keep or install**

```bash
expo install expo-web-browser expo-secure-store

```

**EVM with ethers v6 (optional)**

Public examples that call `ethers` also install and import `@ethersproject/shims`. Add it if you use `ethers` and see runtime errors without it.

**npm**

```bash
npm install ethers @ethersproject/shims

```

**Yarn**

```bash
yarn add ethers @ethersproject/shims

```

**pnpm**

```bash
pnpm add ethers @ethersproject/shims

```

**Bun**

```bash
bun add ethers @ethersproject/shims

```

**Uninstall legacy Web3Auth packages**

Remove packages that only existed for the v8 class API or manual polyfill setup:

```bash
npm uninstall react-native-get-random-values @web3auth/ethereum-provider @web3auth/solana-provider @web3auth/base

```

Do **not** install `react-native-quick-crypto` for v9. Public examples never import it; `withWeb3Auth` configures Metro polyfills for you.

If you previously added `crypto-browserify`, `empty-module`, `readable-stream`, or `buffer` only for Web3Auth, remove those dependencies and delete manual Metro `extraNodeModules` / `resolveRequest` blocks. You do not need to add them back for v9.

**`package.json` target (bare)**

```diff
 "dependencies": {
-  "react-native-get-random-values": "^1.11.0",
-  "@web3auth/ethereum-provider": "^9.3.0",
-  "@web3auth/react-native-sdk": "^8.0.0",
+  "@web3auth/react-native-sdk": "^9.0.0",
   "@toruslabs/react-native-web-browser": "^1.1.0",
   "react-native-encrypted-storage": "^4.0.3"
 },
 "devDependencies": {
+  "@babel/plugin-transform-export-namespace-from": "^7.27.1"
 }

```

**`package.json` target (Expo)**, also set `"main": "index.ts"`.

---

### Step 2, Entry point

Delete `globals.js` (and stop importing it).

**Bare React Native**

index.js

```js
import '@web3auth/react-native-sdk/setup'
import { AppRegistry } from 'react-native'
import App from './App'
import { name as appName } from './app.json'

AppRegistry.registerComponent(appName, () => App)

```

**Expo**

Create `index.ts` and point `"main"` to it:

index.ts

```ts
import '@web3auth/react-native-sdk/setup'
import '@ethersproject/shims'
import { registerRootComponent } from 'expo'
import App from './App'

registerRootComponent(App)

```

Import `@ethersproject/shims` only when your app uses `ethers`. Match [rn-expo-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example).

Add `import '@ethersproject/shims'` at the top of `App.tsx` (before `ethers`) for bare React Native when you use `ethers`.

---

### Step 3, Metro config

v9 replaces manual polyfill wiring. Delete `globals.js`, `react-native-quick-crypto` `resolveRequest` overrides, and hand-rolled `extraNodeModules` for `crypto` / `stream`. Use `withWeb3Auth` only:

**Bare React Native**

metro.config.js

```js
const { getDefaultConfig } = require('@react-native/metro-config')
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')

const config = getDefaultConfig(__dirname)
module.exports = withWeb3Auth(config)

```

**Expo**

metro.config.js

```js
const { getDefaultConfig } = require('expo/metro-config')
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')

const config = getDefaultConfig(__dirname)
module.exports = withWeb3Auth(config)

```

---

### Step 4, Babel config

**Bare React Native**

babel.config.js

```js
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: ['@babel/plugin-transform-export-namespace-from'],
}

```

**Expo**

babel.config.js

```js
module.exports = function (api) {
  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    plugins: ['@babel/plugin-transform-export-namespace-from'],
  }
}

```

---

### Step 5, `web3authConfig.ts`

Create or replace with a `Web3AuthContextConfig`. Move `clientId`, `redirectUrl`, `network`, and optional `whiteLabel` here.

The `chains` and `defaultChainId` fields are **optional** when you configure chains on the [Embedded Wallets dashboard](/embedded-wallets/dashboard/chains-and-networks/). Add them in code when you need custom RPC URLs, Solana, or multi-chain setups (as in [rn-bare-quick-start](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start) and [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example)).

**Dashboard chains (minimal)**

web3authConfig.ts

```typescript
import { WEB3AUTH_NETWORK, type Web3AuthContextConfig } from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
  },
}

export default web3AuthConfig

```

**Local chains array**

web3authConfig.ts

```typescript
import {
  CHAIN_NAMESPACES,
  WEB3AUTH_NETWORK,
  type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId: 'YOUR_CLIENT_ID',
    redirectUrl: 'yourapp://auth',
    network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
    chains: [
      {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: '0xaa36a7',
        rpcTarget: 'https://rpc.ankr.com/eth_sepolia',
        displayName: 'Ethereum Sepolia Testnet',
        blockExplorerUrl: 'https://sepolia.etherscan.io',
        ticker: 'ETH',
        tickerName: 'Ethereum',
      },
    ],
    defaultChainId: '0xaa36a7',
    whiteLabel: {
      appName: 'My App',
      logoLight: 'https://example.com/logo-light.png',
      logoDark: 'https://example.com/logo-dark.png',
      defaultLanguage: 'en',
      mode: 'auto',
      theme: { primary: '#cddc39' },
    },
  },
}

export default web3AuthConfig

```

**Solana**, set `chainNamespace: CHAIN_NAMESPACES.SOLANA` in `chains` when not using dashboard-only config. See [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example). Do not use `SolanaPrivateKeyProvider` or `@web3auth/solana-provider`.

**Removed from v8 options** (delete if present): `privateKeyProvider`, `loginConfig`, `useCoreKitKey`, `useSFAKey`.

---

### Step 6, App root (`Web3AuthProvider`)

**Bare React Native**

App.tsx

```tsx
import '@ethersproject/shims'

import * as WebBrowser from '@toruslabs/react-native-web-browser'
import EncryptedStorage from 'react-native-encrypted-storage'
import { Web3AuthProvider, useWeb3Auth } from '@web3auth/react-native-sdk'
import web3AuthConfig from './web3authConfig'

function RootScreen() {
  const { isConnected, isInitializing } = useWeb3Auth()
  if (isInitializing) return null
  return isConnected ? <HomeScreen /> : <LoginScreen />
}

export default function App() {
  return (
    <Web3AuthProvider webBrowser={WebBrowser} storage={EncryptedStorage} config={web3AuthConfig}>
      <RootScreen />
    </Web3AuthProvider>
  )
}

```

**Expo**

App.tsx

```tsx
import * as WebBrowser from 'expo-web-browser'
import * as SecureStore from 'expo-secure-store'
import { Web3AuthProvider, useWeb3Auth } from '@web3auth/react-native-sdk'
import web3AuthConfig from './web3authConfig'

function RootScreen() {
  const { isConnected, isInitializing } = useWeb3Auth()
  if (isInitializing) return null
  return isConnected ? <HomeScreen /> : <LoginScreen />
}

export default function App() {
  return (
    <Web3AuthProvider webBrowser={WebBrowser} storage={SecureStore} config={web3AuthConfig}>
      <RootScreen />
    </Web3AuthProvider>
  )
}

```

Remove module-level `const web3auth = new Web3Auth(...)` and any `useEffect` that calls `web3auth.init()`.

---

### Step 7, Authentication and session hooks

**Email passwordless**

```tsx
import { AUTH_CONNECTION, useWeb3AuthConnect } from '@web3auth/react-native-sdk'

const { connectTo, loading } = useWeb3AuthConnect()

await connectTo({
  authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
  extraLoginOptions: { login_hint: email },
})

```

**Custom JWT (Firebase, Auth0, Cognito)**

```tsx
await connectTo({
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: 'your-dashboard-connection-id',
  idToken,
  extraLoginOptions: { verifierIdField: 'sub' },
})

```

**Grouped connections (aggregate verifiers)**

```tsx
await connectTo({
  authConnection: AUTH_CONNECTION.GOOGLE,
  authConnectionId: 'w3a-google',
  groupedAuthConnectionId: 'aggregate-sapphire',
})

```

**Logout and user profile**

```tsx
import { useWeb3AuthDisconnect, useWeb3AuthUser } from '@web3auth/react-native-sdk'

const { disconnect } = useWeb3AuthDisconnect()
const { userInfo } = useWeb3AuthUser()

await disconnect()

```

---

### Step 8, Blockchain and Wallet Services

**EVM (ethers v6)**

Match [rn-bare-quick-start](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start): import `@ethersproject/shims` before `ethers`, then use the hook `provider`.

```tsx
import '@ethersproject/shims'

import { useWeb3Auth } from '@web3auth/react-native-sdk'
import { ethers } from 'ethers'

const { provider } = useWeb3Auth()
const ethersProvider = new ethers.BrowserProvider(provider!)
const address = await (await ethersProvider.getSigner()).getAddress()

```

**Solana**

Match [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example): use `web3Auth.signer` as a `TransactionSigner` from `@solana/signers`. Install `@solana/web3.js` for RPC calls.

```tsx
import type { TransactionSigner } from '@solana/signers'
import { useWeb3Auth } from '@web3auth/react-native-sdk'

function SolanaScreen() {
  const { web3Auth } = useWeb3Auth()
  const signer = web3Auth?.signer as TransactionSigner | null
  const address = signer ? String(signer.address) : null
}

```

**Wallet Services**

```tsx
import {
  useEnableMFA,
  useIdentityToken,
  useManageMFA,
  useSignatureRequest,
  useWalletUI,
} from '@web3auth/react-native-sdk'

const { showWalletUI } = useWalletUI()
const { request } = useSignatureRequest()
const { getIdentityToken } = useIdentityToken()
const { enableMFA } = useEnableMFA()
const { manageMFA } = useManageMFA()

await showWalletUI()
await request('personal_sign', ['Hello', address])
await getIdentityToken()

```

---

## Target v9 project layout

After migration, the Web3Auth-related surface should look like this:

```text
index.js | index.ts          # first line: @web3auth/react-native-sdk/setup
metro.config.js             # withWeb3Auth(getDefaultConfig(__dirname))
babel.config.js             # @babel/plugin-transform-export-namespace-from
web3authConfig.ts           # Web3AuthContextConfig export
App.tsx                     # Web3AuthProvider + screens using hooks
# DELETE: globals.js, module-level Web3Auth instance

```

---

## Legacy pattern removals (search and delete)

| Search for                                                | Action                                     |
| --------------------------------------------------------- | ------------------------------------------ |
| `new Web3Auth(` at module scope                           | Remove; use `Web3AuthProvider`             |
| `web3auth.init()`                                         | Remove                                     |
| `EthereumPrivateKeyProvider` / `SolanaPrivateKeyProvider` | Remove; optional `chains` or dashboard     |
| `LOGIN_PROVIDER`                                          | Replace with `AUTH_CONNECTION`             |
| `OPENLOGIN_NETWORK`                                       | Replace with `WEB3AUTH_NETWORK`            |
| `loginConfig:`                                            | Remove; use Dashboard + `authConnectionId` |
| `useCoreKitKey` / `useSFAKey`                             | Remove                                     |
| `://openlogin`                                            | Replace with `://auth`                     |
| `import './globals'`                                      | Remove                                     |
| `SolanaWallet`                                            | Replace with `web3Auth.signer`             |
| `setupProvider(`                                          | Remove (v8 only)                           |

---

## Verification checklist

- `@web3auth/react-native-sdk` is `^9.0.0`
- Legacy Web3Auth-only packages removed (`@web3auth/ethereum-provider`, `@web3auth/solana-provider`, `react-native-get-random-values`, and similar)
- No `react-native-quick-crypto` and no manual Metro crypto polyfills
- `@babel/plugin-transform-export-namespace-from` in Babel config (matches public examples)
- `import '@web3auth/react-native-sdk/setup'` is the **first** line of the entry file
- `globals.js` deleted
- Metro uses `withWeb3Auth(getDefaultConfig(__dirname))` only
- `web3authConfig.ts` exports `Web3AuthContextConfig` with no `privateKeyProvider` (`chains` optional if set on dashboard)
- `redirectUrl` uses `://auth` and matches the dashboard allowlist
- App wrapped in `<Web3AuthProvider webBrowser storage config>`; no `new Web3Auth` or `.init()`
- All logins use `connectTo` + `AUTH_CONNECTION` hooks (no `LOGIN_PROVIDER` or `.login()`)
- Custom JWT uses top-level `idToken` + `authConnectionId`
- EVM uses `useWeb3Auth().provider` with `ethers.BrowserProvider`; Solana uses `web3Auth.signer`
- Expo: `"main": "index.ts"` and custom entry file exists
- App builds on iOS and Android after `npx pod-install` (bare) or `npx expo prebuild` (Expo)

---

## Resources

- [React Native SDK reference](/embedded-wallets/sdk/react-native/)
- [React Native hooks reference](/embedded-wallets/sdk/react-native/hooks/)
- [Metro polyfill troubleshooting](/embedded-wallets/troubleshooting/metro-issues/)
- [Official React Native v9 examples](https://github.com/Web3Auth/web3auth-react-native-examples) (hooks API; preferred over the SDK repo README)  
  - [rn-bare-quick-start](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start), minimal EVM + email OTP
  - [rn-expo-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example), Expo + hooks
  - [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example), Solana + `web3Auth.signer`
  - [rn-bare-firebase-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-firebase-example), custom JWT
  - [rn-bare-aggregate-verifier-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-aggregate-verifier-example), grouped connections
