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

# React Native SDK v10 Migration Guide

This guide upgrades any earlier `@web3auth/react-native-sdk` version (v3 through v9) directly to **v10** (`@web3auth/react-native-sdk@^10`). You don't need intermediate upgrades.

v10 is a hooks-based API. Wrap your app in `Web3AuthProvider` and use hooks such as `useWeb3AuthConnect` and `useWeb3AuthDisconnect`. After sign-in, `useWeb3Auth().connection`exposes `ethereumProvider` for EVM chains and `solanaWallet` for Solana. The `Web3Auth` class is still exported (with `init()`, `connectTo()`, and `logout()`), but this guide uses the recommended provider and hooks.

- **From v9:** the hooks API stays the same. Follow [Migrate from v9](#migrate-from-v9).
- **From v8 or earlier:** follow the [full migration workflow](#migration-workflow).

## React Native version

Check your React Native version before you upgrade the SDK:

- **Bare React Native:** use React Native 0.84 or later. React Native 0.84 ships standards-compliant [URL and URLSearchParams](https://reactnative.dev/blog/2026/02/11/react-native-0.84#url-api-improvements), so don't add `react-native-url-polyfill`. React Native 0.84 requires Node.js 22.11 or later. The official bare examples use React Native 0.84.1 with React 19.2.3.
- **Expo:** the official Expo example still uses Expo SDK 51 (React Native 0.74) until an Expo SDK release ships React Native 0.84 or later.

If your bare app is on an earlier React Native version, upgrade React Native first with the [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/), confirm the app builds, and then upgrade the SDK.

React Native 0.84 doesn't replace the SDK's own setup. You still need the `@web3auth/react-native-sdk/setup` import (for `crypto` and `Buffer`), `withWeb3Auth()` in your Metro config, and `react-native-quick-crypto`.

Compare your result with the official [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).

---

## Agent prompt

### Setup (recommended)

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

```bash
npx skills add web3auth/skill

```

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

React Native SDK v10 migration prompt

```text
ROLE
You are a code-migration agent. Upgrade the open repository to @web3auth/react-native-sdk v10 (the Embedded Wallet SDK). 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
v10 is hooks-based. useWeb3Auth() returns `connection` ({ ethereumProvider, solanaWallet, connectorName, connectorNamespace }), not `provider` or `signer`. The useWeb3AuthConnect() hook's connectTo resolves with Connection | null and doesn't throw (read `error` from the hook); the Web3Auth class method connectTo still throws. The Web3Auth class is still exported (constructor (webBrowser, storage, options), init(), connectTo(), logout()), but migrate to Web3AuthProvider and hooks. Removed: .login() (use connectTo), privateKeyProvider, loginConfig (use dashboard connections or authConnectionConfig), OPENLOGIN_NETWORK, LOGIN_PROVIDER, the WalletResult type, web3Auth.provider and web3Auth.signer, globals.js, manual Metro polyfills, @web3auth/ethereum-provider, @web3auth/solana-provider, SolanaWallet. useCoreKitKey is still supported: keep its existing value, because changing it changes the derived key and wallet address. v10 no longer ships ethers as a dependency.

KNOWLEDGE SOURCES (do not guess Web3Auth APIs from memory)
- Use the "web3auth" skill and Web3Auth MCP server. If the skill is missing, ask the user to run: npx skills add web3auth/skill
- Use this guide: https://metamask-docs-git-ew-combined-sdk-doc-52f4ee-consensys-ddffed67.vercel.app/embedded-wallets/migration-guides/react-native/
- If neither is available, use the PHASE 2 rules below.

PHASE 1: DISCOVERY (read-only)
1. Detect bare React Native vs Expo ("expo" in package.json dependencies or app.json with "expo").
2. Read package.json, index.js/index.ts, App.tsx/App.js, metro.config.js, babel.config.js, globals.js, web3authConfig.ts/js, android/build.gradle, and every file importing "@web3auth/react-native-sdk", "@web3auth/ethereum-provider", "@web3auth/solana-provider", or "@solana/signers".
3. Classify the current version:
   - useWeb3Auth() + `provider` or `web3Auth.signer` → v9.
   - useWeb3Auth() + `connection` → already v10; run verification only.
   - new Web3Auth + init() + connectTo() without privateKeyProvider → v9 or v10 class usage; check the installed version in package.json.
   - new Web3Auth + privateKeyProvider + WEB3AUTH_NETWORK → v8.
   - new Web3Auth + OPENLOGIN_NETWORK → v7 or earlier.
   - new Web3Auth with two constructor args → v3 or earlier.
4. Print a short discovery report (workflow, version, files to change). Ask for confirmation before deleting or renaming files.

PHASE 2: EDITS (in order)

A. package.json
   - Set "@web3auth/react-native-sdk" to ^10.0.0.
   - Ensure react-native-quick-crypto is installed (recommended; it is an optional peer dependency). The SDK setup installs it as global crypto; without it, the Metro config falls back to crypto-browserify. The official examples use react-native-quick-crypto 0.7.x (^0.7.6) on both bare React Native 0.84 and Expo SDK 51; Expo also needs react-native-quick-base64 2.2.2, as in rn-expo-example. Keep an existing working version; ask the user before changing it.
   - Bare React Native must be 0.84 or later (native URL/URLSearchParams; Node.js 22.11 or later). If the app is older, stop and tell the user to upgrade React Native first (React Native Upgrade Helper). Do not add react-native-url-polyfill on 0.84+. Expo apps can stay on Expo SDK 51 (React Native 0.74).
   - Keep or add @react-native-async-storage/async-storage, as the official examples do (optional peer of @metamask/connect-multichain, which the SDK uses).
   - If app code imports ethers, add ethers as a direct dependency (v10 no longer ships it). If app code imports types from @web3auth/auth or @web3auth/no-modal, align them with the v11 majors the SDK uses.
   - Add the optional peers for the features used: viem (>=2.45.0) for viem calls; wagmi (>=3), @wagmi/core (>=3), and @tanstack/react-query (>=5) for @web3auth/react-native-sdk/wagmi; @solana/react-hooks (^1.4.0) for @web3auth/react-native-sdk/solana.
   - The SDK declares engines node >=22 and npm >=10. Flag this if CI or engine-strict installs use older versions.
   - Add devDependency "@babel/plugin-transform-export-namespace-from" if missing.
   - Remove react-native-get-random-values, @web3auth/ethereum-provider, @web3auth/solana-provider, @web3auth/base, and @solana/signers when only Web3Auth code used them.
   - Bare: keep @toruslabs/react-native-web-browser and react-native-encrypted-storage. Expo: keep expo-web-browser, expo-secure-store; add expo-linking and expo-constants if you build redirectUrl with expo-linking.
   - Expo only: "main": "index.ts".

B. Entry file
   - First line: import '@web3auth/react-native-sdk/setup'
   - Remove './globals', 'react-native-get-random-values', and other manual Web3Auth polyfills.
   - Solana apps: add `import './polyfills'` on the second line (see Solana rules in H).

C. metro.config.js
   - module.exports = withWeb3Auth(getDefaultConfig(__dirname)) using require('@web3auth/react-native-sdk/metro-config'). getDefaultConfig comes from '@react-native/metro-config' (bare) or 'expo/metro-config' (Expo).
   - Delete hand-written extraNodeModules for crypto/stream/url; withWeb3Auth provides them.
   - Expo: after withWeb3Auth, keep or add the resolveRequest overrides from rn-expo-example/metro.config.js (react-native-quick-base64, tslib, es-toolkit). Do not delete them.

D. babel.config.js
   - Add '@babel/plugin-transform-export-namespace-from' to plugins.

E. web3authConfig.ts
   - Export a Web3AuthContextConfig: { web3AuthOptions: { clientId, redirectUrl (keep the app's existing value), network, ... } }.
   - chains/defaultChainId are optional when chains are configured on the dashboard.
   - Solana chain IDs must be 0x65 (mainnet), 0x66 (testnet), or 0x67 (devnet).
   - redirectUrl is required here. If the app passed redirectUrl (or mfaLevel) to login(), move redirectUrl into web3AuthOptions.
   - Remove privateKeyProvider, loginConfig, and mfaLevel (mfaLevel is a connectTo parameter).
   - Keep useCoreKitKey unchanged if present. Changing or removing it changes the derived key and wallet address.
   - New optional settings: disableAnalytics, useAAWithExternalWallet. Don't add them unless the user asks.

F. App root
   - Remove module-level `new Web3Auth(...)` and any useEffect calling init().
   - Wrap the tree in <Web3AuthProvider webBrowser={WebBrowser} storage={Storage} config={web3AuthConfig}>.

G. Sign-in and session
   - LOGIN_PROVIDER.X → AUTH_CONNECTION.X; LOGIN_PROVIDER.JWT → AUTH_CONNECTION.CUSTOM + authConnectionId.
   - web3auth.login(...) → useWeb3AuthConnect().connectTo({ authConnection, authConnectionId?, groupedAuthConnectionId?, extraLoginOptions?, mfaLevel? }).
   - Custom JWT: top-level idToken on connectTo (no browser). Remove extraLoginOptions.id_token.
   - loginConfig mapping: single verifier → loginConfig[key].verifier becomes authConnectionId. Aggregate verifier → loginConfig[key].verifier (the aggregate) becomes groupedAuthConnectionId, and loginConfig[key].verifierSubIdentifier becomes authConnectionId.
   - From v8 or earlier: the connectTo hook resolves null on failure instead of throwing like web3auth.login(); replace try/catch-only handling with a check of the return value or `error`. v9 hooks already behave this way.
   - logout() → useWeb3AuthDisconnect().disconnect(); userInfo() → useWeb3AuthUser().userInfo.
   - useIdentityToken().getIdentityToken() → useAuthTokenInfo().getAuthTokenInfo().

H. Blockchain code
   - EVM: useWeb3Auth().provider → useWeb3Auth().connection?.ethereumProvider. Read it only when isConnected is true (never dereference connection during render before the isConnected check). In v9, web3Auth.signer on EVM was an ethers Wallet; replace it with a signer built from connection.ethereumProvider.
   - Solana: remove web3Auth.signer / @solana/signers / SolanaWallet. Install @solana/kit, @solana/react-hooks, @solana/webcrypto-ed25519-polyfill. Wrap the app in SolanaProvider from '@web3auth/react-native-sdk/solana'. Use useSolanaWallet, useSignMessage, useSignTransaction, useSignAndSendTransaction from the same entry point. Add polyfills.js and the @web3auth/auth Metro shim from rn-bare-solana-example. The shim requires a hard-coded nested path (node_modules/@web3auth/react-native-sdk/node_modules/@web3auth/auth); verify that path exists in this repo and adjust it if the package manager hoisted @web3auth/auth.

I. Wallet Services and MFA
   - launchWalletServices(chainConfig) → useWalletUI().showWalletUI().
   - request(chainConfig, method, params) → useSignatureRequest().request(method, params).
   - enableMFA/manageMFA → useEnableMFA().enableMFA() / useManageMFA().manageMFA().

J. Misc
   - Keep the existing redirectUrl. Switching "://openlogin" to "://auth" is optional; if the user wants it, also update the dashboard allowlist and any deep-link intent filters.
   - whiteLabel.name → whiteLabel.appName; whiteLabel.dark → whiteLabel.mode ('light' | 'dark' | 'auto').
   - Android with Gradle 9: @toruslabs/react-native-web-browser 1.1.0 uses jcenter(); propose a patch-package patch deleting the jcenter() lines (mavenCentral() is already listed).
   - Tell the user that existing users may need to sign in again after the upgrade.

CONSTRAINTS
- Do not invent dependency versions. Use ^10.0.0 for the SDK; ask the user about others.
- Do not modify CI, lockfiles, or unrelated code.
- Preserve existing clientId, RPC URLs, scheme, and whitelabel values.

PHASE 3: REPORT
1. A unified diff for every changed file.
2. Files to create and delete.
3. Commands for the user to run (install, uninstall, pod install, expo prebuild).
4. Pass/fail per item in the verification checklist of the migration guide.
5. Manual steps (dashboard allowlist, pod install, expo prebuild).

```


</details>

---

## Version detection

| Signal in code                                                     | Version                             |
| ------------------------------------------------------------------ | ----------------------------------- |
| `useWeb3Auth()` returning `connection`                             | Already v10; run the checklist only |
| `useWeb3Auth()` returning `provider`, or `web3Auth.signer`         | v9                                  |
| `new Web3Auth` + `connectTo()`, no `privateKeyProvider`            | v9 or v10; check `package.json`     |
| `new Web3Auth`, `privateKeyProvider`, `WEB3AUTH_NETWORK`           | v8                                  |
| `new Web3Auth`, `OPENLOGIN_NETWORK`, no `privateKeyProvider`       | v7 or earlier                       |
| `new Web3Auth(WebBrowser, options)` with two constructor arguments | v3 or earlier                       |
| `globals.js` with `crypto-browserify` in Metro                     | v3 to v6 manual polyfills           |
| `whiteLabel.name` or `whiteLabel.dark`                             | v4 or earlier whitelabel            |
| `loginConfig`, `LOGIN_PROVIDER.JWT`                                | v4 to v8 custom authentication      |

---

## Migrate from v9

v9 and v10 share the provider and hooks. The changes are:

| v9                                                                    | v10                                                                                                    |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `useWeb3Auth().provider`                                              | `useWeb3Auth().connection?.ethereumProvider`                                                           |
| `useWeb3Auth().web3Auth.signer` (Solana `TransactionSigner`)          | `connection?.solanaWallet` and the [Solana hooks](/embedded-wallets/sdk/react-native/solana-hooks/)    |
| `useWeb3Auth().web3Auth.signer` (EVM ethers `Wallet`)                 | A signer you build from `connection?.ethereumProvider`                                                 |
| `web3Auth.provider` and `web3Auth.signer` on the class                | Removed; use `web3Auth.connection`                                                                     |
| `connectTo()` resolves with a `WalletResult` (`{ provider, signer }`) | `connectTo()` resolves with a `Connection` (`ethereumProvider`, `solanaWallet`)                        |
| `WalletResult` type export                                            | Removed; use the `Connection` type                                                                     |
| `ethers` installed as an SDK dependency                               | Not included; install `ethers` yourself if your code imports it                                        |
| `@web3auth/auth` 10.x and `@web3auth/no-modal` 10.x                   | 11.x; update direct imports of their types                                                             |
| Node.js 18 and npm 9 or later (`engines`)                             | Node.js 22 and npm 10 or later (`engines`)                                                             |
| Examples on React Native 0.74                                         | Bare: React Native 0.84 or later. Expo: Expo SDK 51. See [React Native version](#react-native-version) |
| None                                                                  | New `web3AuthOptions`: `disableAnalytics`, `useAAWithExternalWallet`                                   |
| `useIdentityToken().getIdentityToken()`                               | `useAuthTokenInfo().getAuthTokenInfo()` (`useIdentityToken` is deprecated)                             |
| None                                                                  | New hooks: `useAccessToken`, `useAuthTokenInfo`, `useRefreshSession`                                   |
| None                                                                  | New entry points: `@web3auth/react-native-sdk/wagmi` and `@web3auth/react-native-sdk/solana`           |
| `mfaLevel` in `web3AuthOptions` (shown in earlier docs)               | Not an SDK option; pass `mfaLevel` to `connectTo`                                                      |
| Any Solana chain ID (earlier docs used `0x1` to `0x3`)                | `0x65` (Mainnet), `0x66` (Testnet), or `0x67` (Devnet), required for the Solana wallet                 |

### 1. Update packages

**npm**

```bash
npm install @web3auth/react-native-sdk@^10.0.0

```

**Yarn**

```bash
yarn add @web3auth/react-native-sdk@^10.0.0

```

**pnpm**

```bash
pnpm add @web3auth/react-native-sdk@^10.0.0

```

**Bun**

```bash
bun add @web3auth/react-native-sdk@^10.0.0

```

Keep `react-native-quick-crypto` installed (recommended): `@web3auth/react-native-sdk/setup`installs it as the global `crypto` object. The official examples use 0.7.x on both React Native 0.84 (bare) and Expo SDK 51. If your bare app is on a React Native version earlier than 0.84, [upgrade React Native](#react-native-version) first. See [Install](/embedded-wallets/sdk/react-native/#1-install-the-sdk-and-its-peer-packages). Remove `@solana/signers` if only Embedded Wallets code used it.

v9 included `ethers` as a dependency and v10 doesn't. If your code imports `ethers`, install it directly:

**npm**

```bash
npm install ethers

```

**Yarn**

```bash
yarn add ethers

```

**pnpm**

```bash
pnpm add ethers

```

**Bun**

```bash
bun add ethers

```

v10 declares `engines` of Node.js 22 or later and npm 10 or later. Update CI if it uses engine-strict installs.

Sessions after upgrading

v10 stores sessions differently from v9, so existing users may need to sign in again after you upgrade. Test session restore with an account that signed in on v9 before you release.

### 2. Replace `provider` with `connection.ethereumProvider`

```diff
- const { provider } = useWeb3Auth()
- const ethersProvider = new ethers.BrowserProvider(provider!)
+ const { connection } = useWeb3Auth()
+ const ethersProvider = new ethers.BrowserProvider(connection!.ethereumProvider!)

```

`connection` is `null` until the user signs in. Read it inside event handlers or after checking `isConnected`, not unconditionally during render.

### 3. Move Solana code to the Solana hooks

Replace `web3Auth.signer` with the hooks from `@web3auth/react-native-sdk/solana`, and set up `SolanaProvider` and the Solana polyfills as described in [Solana hooks](/embedded-wallets/sdk/react-native/solana-hooks/#set-up).

```diff
- import type { TransactionSigner } from '@solana/signers'
- const { web3Auth } = useWeb3Auth()
- const signer = web3Auth?.signer as TransactionSigner | null
- const address = signer ? String(signer.address) : null
+ import { useSolanaWallet } from '@web3auth/react-native-sdk/solana'
+ const { accounts } = useSolanaWallet()
+ const address = accounts?.[0] ?? null

```

### 4. Update `connectTo` handling

```diff
- const { provider } = await connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })
+ const connection = await connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })
+ if (!connection) {
+   // same as v9: read `error` from useWeb3AuthConnect()
+ }

```

### 5. Replace deprecated and moved options

- Replace `useIdentityToken` with [useAuthTokenInfo](/embedded-wallets/sdk/react-native/hooks/useAuthTokenInfo/).
- Move `mfaLevel` from `web3AuthOptions` to `connectTo`.
- Change Solana chain IDs to `0x65`, `0x66`, or `0x67`.

Then run the [verification checklist](#verification-checklist).

---

## API mapping (v8 and earlier to v10)

| Legacy (v3 to v8)                                        | v10 replacement                                                            |         |
| -------------------------------------------------------- | -------------------------------------------------------------------------- | ------- |
| `new Web3Auth(browser, storage, options)` + `init()`     | `<Web3AuthProvider webBrowser storage config>` (initializes automatically) |         |
| `new Web3Auth(browser, options)` (no storage)            | Add storage and use `Web3AuthProvider`                                     |         |
| `OPENLOGIN_NETWORK.*`                                    | `WEB3AUTH_NETWORK.*`                                                       |         |
| `LOGIN_PROVIDER.*`                                       | `AUTH_CONNECTION.*`                                                        |         |
| `web3auth.login({ loginProvider, extraLoginOptions })`   | `useWeb3AuthConnect().connectTo({ authConnection, extraLoginOptions })`    |         |
| `web3auth.logout()`                                      | `useWeb3AuthDisconnect().disconnect()`                                     |         |
| `web3auth.userInfo()`                                    | `useWeb3AuthUser().userInfo`                                               |         |
| `web3auth.connected`                                     | `useWeb3Auth().isConnected`                                                |         |
| `web3auth.provider`, `EthereumPrivateKeyProvider`        | `useWeb3Auth().connection.ethereumProvider`                                |         |
| `SolanaPrivateKeyProvider`, `SolanaWallet`               | `connection.solanaWallet` and the Solana hooks                             |         |
| `web3auth.privKey` / `web3auth.ed25519Key`               | No direct getter; use the provider or Solana hooks                         |         |
| `privateKeyProvider` with a `chainConfig`                | Optional `chains` in `web3AuthOptions` or chains on the dashboard          |         |
| `loginConfig` (single verifier): `verifier`              | Dashboard connection (or `authConnectionConfig`) + `authConnectionId`      |         |
| `loginConfig` (aggregate): `verifier`                    | `groupedAuthConnectionId` in `connectTo`                                   |         |
| `loginConfig` (aggregate): `verifierSubIdentifier`       | `authConnectionId` in `connectTo`                                          |         |
| `LOGIN_PROVIDER.JWT` + `id_token` in `extraLoginOptions` | `AUTH_CONNECTION.CUSTOM` + `authConnectionId` + top-level `idToken`        |         |
| `useCoreKitKey`                                          | Unchanged; keep the existing value (changing it changes the address)       |         |
| `mfaLevel` in `login()`                                  | `mfaLevel` in `connectTo`                                                  |         |
| `redirectUrl` in `login()`                               | `redirectUrl` in `web3AuthOptions` (required)                              |         |
| `launchWalletServices(chainConfig)`                      | `useWalletUI().showWalletUI()`                                             |         |
| `request(chainConfig, method, params)`                   | `useSignatureRequest().request(method, params)`                            |         |
| `scheme://openlogin`                                     | Keep it, or switch to `scheme://auth` and update the allowlist             |         |
| `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'` as the first line              |         |
| Manual Metro `extraNodeModules`                          | `withWeb3Auth(getDefaultConfig(__dirname))`                                |         |

---

## Migration workflow

Run these steps in order. Skip steps your project already satisfies.

### Step 1: Dependencies

**Bare React Native**

**Expo**

```bash
npm install @web3auth/react-native-sdk@^10.0.0 @toruslabs/react-native-web-browser react-native-encrypted-storage
npm install --save-dev @babel/plugin-transform-export-namespace-from

```

**npm**

```bash
yarn add @web3auth/react-native-sdk@^10.0.0 @toruslabs/react-native-web-browser react-native-encrypted-storage
yarn add --dev @babel/plugin-transform-export-namespace-from

```

**Yarn**

```bash
pnpm add @web3auth/react-native-sdk@^10.0.0 @toruslabs/react-native-web-browser react-native-encrypted-storage
pnpm add --save-dev @babel/plugin-transform-export-namespace-from

```

**pnpm**

```bash
bun add @web3auth/react-native-sdk@^10.0.0 @toruslabs/react-native-web-browser react-native-encrypted-storage
bun add --dev @babel/plugin-transform-export-namespace-from

```

**Bun**

```bash
npx expo install @web3auth/react-native-sdk expo-web-browser expo-secure-store expo-linking expo-constants
npm install --save-dev @babel/plugin-transform-export-namespace-from

```

Bare apps must be on React Native 0.84 or later before you continue; see [React Native version](#react-native-version).

Install `react-native-quick-crypto`. The official examples use 0.7.x (`^0.7.6`) on both React Native 0.84 (bare) and Expo SDK 51. On Expo, also install `react-native-quick-base64` 2.2.2, as the [rn-expo-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example)does. To run on Android devices with 16 KB memory pages, use 1.x instead; see [Install](/embedded-wallets/sdk/react-native/#1-install-the-sdk-and-its-peer-packages).

Install the optional peer packages for the features you use:

- `viem` (2.45.0 or later) for the EVM examples in this guide.
- `wagmi` (3.x or later), `@wagmi/core` (3.x or later), and `@tanstack/react-query` (5.x or later) for `@web3auth/react-native-sdk/wagmi`.
- `@solana/react-hooks` (1.4.0 or later) for `@web3auth/react-native-sdk/solana`.
- `ethers`, if your code imports it. v10 doesn't install it for you (only v9 did).
- `@react-native-async-storage/async-storage`, which the official examples install. It's an optional peer dependency of `@metamask/connect-multichain`, which the SDK uses.

v10 declares `engines` of Node.js 22 or later and npm 10 or later. Update CI if it uses engine-strict installs.

Remove packages that only existed for the class API or manual polyfills:

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

```

On React Native 0.84 or later, also remove `react-native-url-polyfill` and any `react-native-url-polyfill/auto` import.

If you added `crypto-browserify`, `empty-module`, `readable-stream`, or `buffer` only for Embedded Wallets, remove them along with your manual Metro `extraNodeModules`. `withWeb3Auth` provides these aliases.

Android builds with Gradle 9

React Native 0.84 projects use Gradle 9. `@toruslabs/react-native-web-browser` 1.1.0 calls `jcenter()`, which Gradle 9 removed. Delete the `jcenter()` lines in `node_modules/@toruslabs/react-native-web-browser/android/build.gradle`(`mavenCentral()` is already listed) and persist the change with [patch-package](https://www.npmjs.com/package/patch-package).

### Step 2: Entry file

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 set `"main": "index.ts"` in `package.json`:

index.ts

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

registerRootComponent(App)

```

### Step 3: Metro config

**Bare React Native**

metro.config.js

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

module.exports = withWeb3Auth(getDefaultConfig(__dirname))

```

**Expo**

This matches [rn-expo-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example). The `resolveRequest` overrides for `react-native-quick-base64`, `tslib`, and `es-toolkit` are part of the working setup. Keep them.

metro.config.js

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

const config = withWeb3Auth(getDefaultConfig(__dirname))
const baseResolve = config.resolver.resolveRequest

const pkgRoot = name => path.dirname(require.resolve(`${name}/package.json`))
const quickBase64Entry = path.join(pkgRoot('react-native-quick-base64'), 'lib/module/index.js')
const esToolkitWordsEntry = path.join(pkgRoot('es-toolkit'), 'dist/string/words.mjs')
const esToolkitCompatWords = `${path.sep}es-toolkit${path.sep}dist${path.sep}compat${path.sep}string${path.sep}words.`

config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (moduleName === 'react-native-quick-base64') {
    return { type: 'sourceFile', filePath: quickBase64Entry }
  }
  if (moduleName === 'tslib') {
    return { type: 'sourceFile', filePath: require.resolve('tslib/tslib.js') }
  }

  const resolved = baseResolve(context, moduleName, platform)
  if (resolved?.type === 'sourceFile' && resolved.filePath.includes(esToolkitCompatWords)) {
    return { type: 'sourceFile', filePath: esToolkitWordsEntry }
  }
  return resolved
}

module.exports = config

```

### Step 4: Babel config

Add `@babel/plugin-transform-export-namespace-from` to `plugins`. For Expo, see the full [Babel configuration](/embedded-wallets/sdk/react-native/#babel).

babel.config.js

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

```

### Step 5: `web3authConfig.ts`

Move `clientId`, `redirectUrl`, `network`, and optional settings into a `Web3AuthContextConfig`. `redirectUrl` is required here, including if you passed it to `login()` before. Keep your existing redirect URL. If you switch from `://openlogin` to `://auth`, allowlist the new URL on the dashboard and update any deep-link configuration. `chains` is optional when you configure chains on the [dashboard](/embedded-wallets/dashboard/chains-and-networks/).

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,
    whiteLabel: {
      appName: 'My App',
      mode: 'auto',
    },
  },
}

export default web3AuthConfig

```

Delete `privateKeyProvider`, `loginConfig`, and `mfaLevel` from the options. If you set `useCoreKitKey`, keep its existing value: changing it changes the derived key and the user's wallet address. v10 adds the optional `disableAnalytics` and `useAAWithExternalWallet` settings. For Solana, use chain IDs `0x65`, `0x66`, or `0x67`. See [Configure the SDK](/embedded-wallets/sdk/react-native/#configure-the-sdk).

### Step 6: App root

App.tsx

```tsx
import * as WebBrowser from '@toruslabs/react-native-web-browser' // Expo: 'expo-web-browser'
import { Web3AuthProvider, useWeb3Auth } from '@web3auth/react-native-sdk'
import EncryptedStorage from 'react-native-encrypted-storage' // Expo: * as SecureStore from 'expo-secure-store'

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

```

Remove module-level `new Web3Auth(...)` and any `useEffect` that calls `init()`. The `Web3Auth`class is still exported in v10, but `Web3AuthProvider` initializes the SDK for you and is the recommended pattern.

Sessions after upgrading

v10 stores sessions differently from earlier versions, so existing users may need to sign in again after you upgrade. Test session restore with an account that signed in on your current version before you release.

### Step 7: Sign-in and session hooks

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

const { connectTo, error } = useWeb3AuthConnect()
const { disconnect } = useWeb3AuthDisconnect()
const { userInfo } = useWeb3AuthUser()

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

// Custom JWT (no browser)
await connectTo({
  authConnection: AUTH_CONNECTION.CUSTOM,
  authConnectionId: '<YOUR_CONNECTION_ID>',
  idToken,
})

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

await disconnect()

```

Unlike `web3auth.login()`, the `connectTo` hook resolves with `null` instead of throwing when sign-in fails. Check the result or `error`. For the custom JWT flow's token requirements, see [Custom authentication](/embedded-wallets/sdk/react-native/advanced/custom-authentication/#bring-your-own-jwt-idtoken).

### Step 8: Blockchain calls and Wallet Services

**EVM:**

```tsx
import { useWeb3Auth } from '@web3auth/react-native-sdk'
import { createWalletClient, custom } from 'viem'

const { connection } = useWeb3Auth()

// Inside an event handler, after sign-in
const walletClient = createWalletClient({ transport: custom(connection!.ethereumProvider!) })
const [address] = await walletClient.getAddresses()

```

To use Wagmi, see [Ethereum hooks (Wagmi)](/embedded-wallets/sdk/react-native/ethereum-hooks/).

**Solana:** follow [Solana hooks](/embedded-wallets/sdk/react-native/solana-hooks/). If you copy the `@web3auth/auth` Metro shim from [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example), check its `require` path. The shim loads `node_modules/@web3auth/react-native-sdk/node_modules/@web3auth/auth`, which doesn't exist if your package manager hoists `@web3auth/auth` to the top-level `node_modules`. Adjust the path to match your install.

**Wallet Services and MFA:**

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

const { showWalletUI } = useWalletUI()
const { request } = useSignatureRequest()
const { getAuthTokenInfo } = useAuthTokenInfo()
const { enableMFA } = useEnableMFA()
const { manageMFA } = useManageMFA()

```

---

## Legacy pattern removals

| Search for                                                | Action                                     |
| --------------------------------------------------------- | ------------------------------------------ |
| `new Web3Auth(` at module scope                           | Replace with `Web3AuthProvider`            |
| `.init()`                                                 | Remove (the provider initializes)          |
| `.login(`                                                 | Replace with `connectTo`                   |
| `EthereumPrivateKeyProvider` / `SolanaPrivateKeyProvider` | Remove; use `chains` or dashboard chains   |
| `LOGIN_PROVIDER`                                          | Replace with `AUTH_CONNECTION`             |
| `OPENLOGIN_NETWORK`                                       | Replace with `WEB3AUTH_NETWORK`            |
| `loginConfig:`                                            | Remove; use a dashboard connection         |
| `useCoreKitKey`                                           | Keep unchanged (it affects the address)    |
| `://openlogin`                                            | Optional: switch to `://auth`              |
| `WalletResult`, `web3Auth.provider`                       | Replace with `Connection`, `connection`    |
| `from 'ethers'`                                           | Install `ethers` as a direct dependency    |
| `import './globals'`                                      | Remove                                     |
| `SolanaWallet`, `web3Auth.signer`, `@solana/signers`      | Replace with the Solana hooks              |
| `useWeb3Auth().provider`                                  | Replace with `connection.ethereumProvider` |
| `useIdentityToken`                                        | Replace with `useAuthTokenInfo`            |

---

## Verification checklist

- `@web3auth/react-native-sdk` is `^10.0.0`.
- Bare apps run React Native 0.84 or later without `react-native-url-polyfill`. Expo apps run Expo SDK 51 or later.
- `react-native-quick-crypto` is installed.
- Legacy packages are removed (`@web3auth/ethereum-provider`, `@web3auth/solana-provider`, `react-native-get-random-values`).
- `import '@web3auth/react-native-sdk/setup'` is the first line of the entry file, and `globals.js` is deleted.
- Metro uses `withWeb3Auth(getDefaultConfig(__dirname))`. On Expo, the `resolveRequest` overrides from `rn-expo-example` are in place.
- `ethers` is a direct dependency if your code imports it.
- Babel includes `@babel/plugin-transform-export-namespace-from`.
- `web3authConfig.ts` exports a `Web3AuthContextConfig` without `privateKeyProvider`, `loginConfig`, or `mfaLevel`, and with any existing `useCoreKitKey` value unchanged.
- `redirectUrl` is set in `web3AuthOptions` and allowlisted on the dashboard.
- The app is wrapped in `Web3AuthProvider`, with no `.login()` calls.
- Aggregate verifiers map `verifier` to `groupedAuthConnectionId` and `verifierSubIdentifier` to `authConnectionId`.
- Users who signed in before the upgrade can restore their session or sign in again.
- Sign-in uses `connectTo` with `AUTH_CONNECTION`, and the code handles a `null` result.
- EVM code uses `connection.ethereumProvider`, and Solana code uses the Solana hooks.
- Solana chain IDs are `0x65`, `0x66`, or `0x67`.
- Expo: `"main": "index.ts"` and the entry file exists.
- The app builds and signs in on iOS and Android after `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/)
- [React Native examples](https://github.com/Web3Auth/web3auth-react-native-examples)  
  - [rn-bare-quick-start](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start): EVM and email passwordless
  - [rn-expo-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example): Expo
  - [rn-bare-solana-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-solana-example): Solana hooks
  - [rn-bare-firebase-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-firebase-example): custom JWT
  - [rn-bare-auth0-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-auth0-example): Auth0
  - [rn-bare-aggregate-verifier-example](https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-aggregate-verifier-example): grouped connections
