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.
- From v9: the hooks API stays the same. Follow Migrate from v9.
- From v8 or earlier: follow the full migration workflow.
Compare your result with the official React Native examples, for example rn-bare-quick-start and 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:
npx skills add web3auth/skill
Full agent prompt: expand, then use Copy on the code block
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 code | Version |
|---|---|
useWeb3Auth() returning connection | Already v10; run the checklist only |
useWeb3Auth() returning provider, or web3Auth.signer | v9 |
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, useSFAKey | 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 |
connectTo() resolves with a WalletResult ({ provider, signer }) | connectTo() resolves with a Connection (ethereumProvider, solanaWallet) |
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
- Yarn
- pnpm
- Bun
npm install @web3auth/react-native-sdk@^10.0.0
yarn add @web3auth/react-native-sdk@^10.0.0
pnpm add @web3auth/react-native-sdk@^10.0.0
bun add @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
useIdentityTokenwithuseAuthTokenInfo. - Move
mfaLevelfromweb3AuthOptionstoconnectTo. - Change Solana chain IDs to
0x65,0x66, or0x67.
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.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 + verifier | Dashboard connection + authConnectionId in connectTo |
verifierSubIdentifier | groupedAuthConnectionId in connectTo |
LOGIN_PROVIDER.JWT + id_token in extraLoginOptions | AUTH_CONNECTION.CUSTOM + authConnectionId + top-level idToken |
useSFAKey | Removed |
mfaLevel in constructor options | mfaLevel in connectTo |
launchWalletServices(chainConfig) | useWalletUI().showWalletUI() |
request(chainConfig, method, params) | useSignatureRequest().request(method, params) |
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' 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
- npm
- Yarn
- pnpm
- Bun
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
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
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
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
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
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.
@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.
- Bare React Native
- Expo
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 set "main": "index.ts" in package.json:
import '@web3auth/react-native-sdk/setup'
import { registerRootComponent } from 'expo'
import App from './App'
registerRootComponent(App)
Step 3: Metro config
- Bare React Native
- Expo
const { getDefaultConfig } = require('@react-native/metro-config')
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')
module.exports = withWeb3Auth(getDefaultConfig(__dirname))
const { getDefaultConfig } = require('expo/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.
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.
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
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 for | Action |
|---|---|
new Web3Auth( at module scope | Remove; use Web3AuthProvider |
.init() | Remove |
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 |
useSFAKey | Remove |
://openlogin | Replace with ://auth |
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-sdkis^10.0.0.react-native-quick-cryptois 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, andglobals.jsis deleted.- Metro uses
withWeb3Auth(getDefaultConfig(__dirname)). - Babel includes
@babel/plugin-transform-export-namespace-from. web3authConfig.tsexports aWeb3AuthContextConfigwithoutprivateKeyProvider,loginConfig, ormfaLevel.redirectUrluses://authand is allowlisted on the dashboard.- The app is wrapped in
Web3AuthProvider, with nonew Web3Author.init(). - Sign-in uses
connectTowithAUTH_CONNECTION, and the code handles anullresult. - EVM code uses
connection.ethereumProvider, and Solana code uses the Solana hooks. - Solana chain IDs are
0x65,0x66, or0x67. - Expo:
"main": "index.ts"and the entry file exists. - The app builds and signs in on iOS and Android after
pod install(bare) ornpx expo prebuild(Expo).
Resources
- React Native SDK reference
- React Native hooks reference
- Metro polyfill troubleshooting
- React Native examples
- rn-bare-quick-start: EVM and email passwordless
- rn-expo-example: Expo
- rn-bare-solana-example: Solana hooks
- rn-bare-firebase-example: custom JWT
- rn-bare-auth0-example: Auth0
- rn-bare-aggregate-verifier-example: grouped connections