For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at the same URL with .md appended (or via Accept: text/markdown).
Skip to main content

React Native SDK 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.

Compare your result with the official React Native examples, for example rn-bare-quick-start and rn-bare-solana-example.


Agent prompt​

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:

npx skills add web3auth/skill
Full agent prompt: expand, then use Copy on the code block
React Native SDK v10 migration prompt
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 legacy class pattern (new Web3Auth(...), .init(), .login(), privateKeyProvider, loginConfig, useSFAKey, OPENLOGIN_NETWORK, LOGIN_PROVIDER, 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. If the skill is missing, ask the user to run: npx skills add web3auth/skill
- Use this guide: https://docs.metamask.io/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 + 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. The SDK setup installs it as global crypto, and sign-in fails without a working install. React Native 0.75+ with the New Architecture: react-native-quick-crypto 1.x plus react-native-nitro-modules and react-native-quick-base64 (3.x or later). Earlier React Native or the old architecture: react-native-quick-crypto 0.7.x. Keep an existing working version; ask the user before changing it.
- 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 and quick-crypto resolveRequest overrides.

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

E. web3authConfig.ts
- Export a Web3AuthContextConfig: { web3AuthOptions: { clientId, redirectUrl ('scheme://auth'), network, ... } }.
- chains/defaultChainId are optional when chains are configured on the dashboard.
- Solana chain IDs must be 0x65 (mainnet), 0x66 (testnet), or 0x67 (devnet).
- Remove privateKeyProvider, loginConfig, useSFAKey, and mfaLevel (mfaLevel moves to connectTo).

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

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
- Redirect URLs ending in "://openlogin" become "://auth". Remind the user to update the dashboard allowlist.
- 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 replacing jcenter() with mavenCentral().

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

Version detection​

Signal in codeVersion
useWeb3Auth() returning connectionAlready v10; run the checklist only
useWeb3Auth() returning provider, or web3Auth.signerv9
new Web3Auth, privateKeyProvider, WEB3AUTH_NETWORKv8
new Web3Auth, OPENLOGIN_NETWORK, no privateKeyProviderv7 or earlier
new Web3Auth(WebBrowser, options) with two constructor argumentsv3 or earlier
globals.js with crypto-browserify in Metrov3 to v6 manual polyfills
whiteLabel.name or whiteLabel.darkv4 or earlier whitelabel
loginConfig, LOGIN_PROVIDER.JWT, useSFAKeyv8 custom authentication

Migrate from v9​

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

v9v10
useWeb3Auth().provideruseWeb3Auth().connection?.ethereumProvider
useWeb3Auth().web3Auth.signer (Solana TransactionSigner)connection?.solanaWallet and the Solana hooks
connectTo() resolves with a WalletResult ({ provider, signer })connectTo() resolves with a Connection (ethereumProvider, solanaWallet)
useIdentityToken().getIdentityToken()useAuthTokenInfo().getAuthTokenInfo() (useIdentityToken is deprecated)
NoneNew hooks: useAccessToken, useAuthTokenInfo, useRefreshSession
NoneNew 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 install @web3auth/react-native-sdk@^10.0.0

Keep react-native-quick-crypto installed: @web3auth/react-native-sdk/setup installs it as the global crypto object that sign-in uses. Use 1.x for React Native 0.75 or later with the New Architecture, and 0.7.x for earlier versions. See Install. Remove @solana/signers if only Embedded Wallets code used it.

2. Replace provider with connection.ethereumProvider​

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

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

- 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.
  • Move mfaLevel from web3AuthOptions to connectTo.
  • Change Solana chain IDs to 0x65, 0x66, or 0x67.

Then run the 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.connecteduseWeb3Auth().isConnected
web3auth.provider, EthereumPrivateKeyProvideruseWeb3Auth().connection.ethereumProvider
SolanaPrivateKeyProvider, SolanaWalletconnection.solanaWallet and the Solana hooks
web3auth.privKey / web3auth.ed25519KeyNo direct getter; use the provider or Solana hooks
privateKeyProvider with a chainConfigOptional chains in web3AuthOptions or chains on the dashboard
loginConfig + verifierDashboard connection + authConnectionId in connectTo
verifierSubIdentifiergroupedAuthConnectionId in connectTo
LOGIN_PROVIDER.JWT + id_token in extraLoginOptionsAUTH_CONNECTION.CUSTOM + authConnectionId + top-level idToken
useSFAKeyRemoved
mfaLevel in constructor optionsmfaLevel in connectTo
launchWalletServices(chainConfig)useWalletUI().showWalletUI()
request(chainConfig, method, params)useSignatureRequest().request(method, params)
scheme://openloginscheme://auth
whiteLabel.namewhiteLabel.appName
whiteLabel.dark: booleanwhiteLabel.mode: 'light' | 'dark' | 'auto'
import './globals', react-native-get-random-valuesimport '@web3auth/react-native-sdk/setup' as the first line
Manual Metro extraNodeModuleswithWeb3Auth(getDefaultConfig(__dirname))

Migration workflow​

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

Step 1: Dependencies​

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

Install react-native-quick-crypto in the version that matches your app: 1.x (with react-native-nitro-modules and react-native-quick-base64 3.x or later) for React Native 0.75 or later with the New Architecture, or 0.7.x for earlier versions. See Install.

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

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

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

@toruslabs/react-native-web-browser 1.1.0 calls jcenter(), which Gradle 9 (used by newer React Native versions such as 0.84) removed. Replace jcenter() with mavenCentral() in node_modules/@toruslabs/react-native-web-browser/android/build.gradle and persist the change with patch-package.

Step 2: Entry file​

Delete globals.js and stop importing it.

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)

Step 3: Metro config​

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

module.exports = withWeb3Auth(getDefaultConfig(__dirname))

Step 4: Babel config​

Add @babel/plugin-transform-export-namespace-from to plugins. For Expo, see the full Babel configuration.

babel.config.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. chains is optional when you configure chains on the dashboard.

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

export default web3AuthConfig

Delete privateKeyProvider, loginConfig, useSFAKey, and mfaLevel from the options. For Solana, use chain IDs 0x65, 0x66, or 0x67. See Configure the SDK.

Step 6: App root​

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

Step 7: Sign-in and session hooks​

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.

Step 8: Blockchain calls and Wallet Services​

EVM:

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

Solana: follow Solana hooks.

Wallet Services and MFA:

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 forAction
new Web3Auth( at module scopeRemove; use Web3AuthProvider
.init()Remove
EthereumPrivateKeyProvider / SolanaPrivateKeyProviderRemove; use chains or dashboard chains
LOGIN_PROVIDERReplace with AUTH_CONNECTION
OPENLOGIN_NETWORKReplace with WEB3AUTH_NETWORK
loginConfig:Remove; use a dashboard connection
useSFAKeyRemove
://openloginReplace with ://auth
import './globals'Remove
SolanaWallet, web3Auth.signer, @solana/signersReplace with the Solana hooks
useWeb3Auth().providerReplace with connection.ethereumProvider
useIdentityTokenReplace with useAuthTokenInfo

Verification checklist​

  • @web3auth/react-native-sdk is ^10.0.0.
  • react-native-quick-crypto is installed in a version that matches your app (1.x for React Native 0.75+ with the New Architecture, 0.7.x otherwise).
  • 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)).
  • Babel includes @babel/plugin-transform-export-namespace-from.
  • web3authConfig.ts exports a Web3AuthContextConfig without privateKeyProvider, loginConfig, or mfaLevel.
  • redirectUrl uses ://auth and is allowlisted on the dashboard.
  • The app is wrapped in Web3AuthProvider, with no new Web3Auth or .init().
  • 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​