> 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[​](#agent-prompt "Direct link to Agent prompt")

### Setup (recommended)[​](#setup-recommended "Direct link to 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:

```
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

```
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-react-native-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[​](#version-detection "Direct link to 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)[​](#api-mapping-legacy--v9 "Direct link to 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`[​](#login%5Fprovider--auth%5Fconnection "Direct link to 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[​](#migration-workflow "Direct link to Migration workflow")

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

### Step 1, Dependencies[​](#step-1-dependencies "Direct link to Step 1, Dependencies")

**Install**

- npm
- Yarn
- pnpm
- Bun

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

```

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

```

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

```

```
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
- Yarn
- pnpm
- Bun

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

```

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

```

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

```

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

```

**Expo, keep or install**

```
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
- Yarn
- pnpm
- Bun

```
npm install ethers @ethersproject/shims

```

```
yarn add ethers @ethersproject/shims

```

```
pnpm add ethers @ethersproject/shims

```

```
bun add ethers @ethersproject/shims

```

**Uninstall legacy Web3Auth packages**

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

```
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)**

```
 "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[​](#step-2-entry-point "Direct link to Step 2, Entry point")

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

- Bare React Native
- Expo

index.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)

```

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

index.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[​](#step-3-metro-config "Direct link to 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
- Expo

metro.config.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)

```

metro.config.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[​](#step-4-babel-config "Direct link to Step 4, Babel config")

- Bare React Native
- Expo

babel.config.js

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

```

babel.config.js

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

```

---

### Step 5, `web3authConfig.ts`[​](#step-5-web3authconfigts "Direct link to step-5-web3authconfigts")

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)
- Local chains array

web3authConfig.ts

```
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

```

web3authConfig.ts

```
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`)[​](#step-6-app-root-web3authprovider "Direct link to step-6-app-root-web3authprovider")

- Bare React Native
- Expo

App.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>
  )
}

```

App.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[​](#step-7-authentication-and-session-hooks "Direct link to Step 7, Authentication and session hooks")

**Email passwordless**

```
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)**

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

```

**Grouped connections (aggregate verifiers)**

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

```

**Logout and user profile**

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

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

await disconnect()

```

---

### Step 8, Blockchain and Wallet Services[​](#step-8-blockchain-and-wallet-services "Direct link to 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`.

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

```
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**

```
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[​](#target-v9-project-layout "Direct link to Target v9 project layout")

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

```
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)[​](#legacy-pattern-removals-search-and-delete "Direct link to 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[​](#verification-checklist "Direct link to 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[​](#resources "Direct link to 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
