Embedded Wallets SDK for React Native
Overview
The MetaMask Embedded Wallets SDK for React Native lets you add social login and embedded wallet functionality to your iOS and Android apps. Version 9 is a hooks-first API: you wrap your app in a Web3AuthProvider and access all functionality through React hooks — no class instance, no useEffect-based initialisation.
Use the single Migrate to v9 guide. It includes an LLM agent prompt, a full legacy-to-v9 API map, and step-by-step file targets for any prior @web3auth/react-native-sdk version.
Requirements
- React Native 0.71 or later (bare workflow)
- Expo SDK 48 or later (managed workflow)
- iOS 14 or later
- Android API level 31 or later (target SDK)
Prerequisites
Set up your project on the Embedded Wallets dashboard:
- Create a new project and copy the Client ID.
- Go to Allowed Origins and add your app's deep link scheme (for example,
web3authrnexample://auth).
See the dashboard setup guide for more detail.
Installation
1. Install the SDK
- npm
- Yarn
- pnpm
- Bun
npm install @web3auth/react-native-sdk
yarn add @web3auth/react-native-sdk
pnpm add @web3auth/react-native-sdk
bun add @web3auth/react-native-sdk
2. Install helper modules
The SDK requires a WebBrowser and a persistent Storage implementation. The correct packages differ between bare React Native and Expo:
- Bare React Native
- Expo
- npm
- Yarn
- pnpm
- Bun
npm install @toruslabs/react-native-web-browser react-native-encrypted-storage
npm install --save-dev @babel/plugin-transform-export-namespace-from
yarn add @toruslabs/react-native-web-browser react-native-encrypted-storage
yarn add --dev @babel/plugin-transform-export-namespace-from
pnpm add @toruslabs/react-native-web-browser react-native-encrypted-storage
pnpm add --save-dev @babel/plugin-transform-export-namespace-from
bun add @toruslabs/react-native-web-browser react-native-encrypted-storage
bun add --dev @babel/plugin-transform-export-namespace-from
- npm
- Yarn
- pnpm
- Bun
npm install expo-web-browser expo-secure-store
npm install --save-dev @babel/plugin-transform-export-namespace-from
yarn add expo-web-browser expo-secure-store
yarn add --dev @babel/plugin-transform-export-namespace-from
pnpm add expo-web-browser expo-secure-store
pnpm add --save-dev @babel/plugin-transform-export-namespace-from
bun add expo-web-browser expo-secure-store
bun add --dev @babel/plugin-transform-export-namespace-from
3. Android setup
In your android/app/build.gradle, ensure the compile SDK version is 31 or higher:
compileSdkVersion = 31
targetSdkVersion = 31
Add the intent filter with your custom scheme to AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- replace with your own scheme -->
<data android:scheme="web3authrnexample" />
</intent-filter>
Also set android:exported="true" on your main activity:
<activity
android:name=".MainActivity"
android:exported="true"
...>
4. iOS setup
In your Podfile, set the minimum platform to iOS 14:
platform :ios, '14'
Then install Pods:
cd ios && pod install
Register your redirect URL (for example, web3authrnexample://auth) in the Allowed Origins section of the dashboard. No additional Info.plist entry is required.
5. Expo setup
Add your scheme to app.json:
{
"expo": {
"scheme": "web3authexpoexample"
}
}
The SDK does not work with the Expo Go app. Use a custom dev client or an EAS build. Run npx expo prebuild before building.
Configure polyfills and bundler
Entry point
Add import "@web3auth/react-native-sdk/setup" as the first line of your app's entry file. This single import replaces the globals.js / react-native-get-random-values pattern used in v8.
- Bare React Native
- Expo
import '@web3auth/react-native-sdk/setup' // must be first
import { AppRegistry } from 'react-native'
import App from './App'
import { name as appName } from './app.json'
AppRegistry.registerComponent(appName, () => App)
Create index.ts and change "main" to "index.ts" in package.json:
import '@web3auth/react-native-sdk/setup' // must be first
import { registerRootComponent } from 'expo'
import App from './App'
registerRootComponent(App)
Metro bundler
- Bare React Native
- Expo
const { getDefaultConfig } = require('@react-native/metro-config')
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')
const config = getDefaultConfig(__dirname)
module.exports = withWeb3Auth(config)
const { getDefaultConfig } = require('expo/metro-config')
const { withWeb3Auth } = require('@web3auth/react-native-sdk/metro-config')
const config = getDefaultConfig(__dirname)
module.exports = withWeb3Auth(config)
Babel config
- Bare React Native
- Expo
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: ['@babel/plugin-transform-export-namespace-from'],
}
module.exports = function (api) {
api.cache(true)
return {
presets: ['babel-preset-expo'],
plugins: ['@babel/plugin-transform-export-namespace-from'],
}
}
SDK configuration
Create a dedicated web3authConfig.ts file. This is the only file you need to edit to change SDK settings, chains, or optional features.
- Basic (EVM)
- Solana
- With Account Abstraction
import {
CHAIN_NAMESPACES,
WEB3AUTH_NETWORK,
type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'
const web3AuthConfig: Web3AuthContextConfig = {
web3AuthOptions: {
clientId: 'YOUR_CLIENT_ID', // from developer.metamask.io
redirectUrl: 'web3authrnexample://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',
},
}
export default web3AuthConfig
import {
CHAIN_NAMESPACES,
WEB3AUTH_NETWORK,
type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'
const web3AuthConfig: Web3AuthContextConfig = {
web3AuthOptions: {
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'web3authrnexample://auth',
network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
chains: [
{
chainNamespace: CHAIN_NAMESPACES.SOLANA,
chainId: '0x2', // Solana Testnet
rpcTarget: 'https://api.testnet.solana.com',
displayName: 'Solana Testnet',
blockExplorerUrl: 'https://explorer.solana.com',
ticker: 'SOL',
tickerName: 'Solana',
},
],
defaultChainId: '0x2',
},
}
export default web3AuthConfig
import {
CHAIN_NAMESPACES,
WEB3AUTH_NETWORK,
type AccountAbstractionConfig,
type Web3AuthContextConfig,
} from '@web3auth/react-native-sdk'
const aaConfig: AccountAbstractionConfig = {
smartAccountType: 'safe',
}
const web3AuthConfig: Web3AuthContextConfig = {
web3AuthOptions: {
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'web3authrnexample://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',
accountAbstractionConfig: aaConfig,
},
}
export default web3AuthConfig
Set up Web3AuthProvider
Web3AuthProvider is the React context provider that initialises the SDK and makes all hooks available to the component tree.
- Bare React Native
- Expo
import WebBrowser from '@toruslabs/react-native-web-browser'
import EncryptedStorage from 'react-native-encrypted-storage'
import { Web3AuthProvider } from '@web3auth/react-native-sdk'
import web3AuthConfig from './web3authConfig'
export default function App() {
return (
<Web3AuthProvider webBrowser={WebBrowser} storage={EncryptedStorage} config={web3AuthConfig}>
<Screen />
</Web3AuthProvider>
)
}
import * as WebBrowser from 'expo-web-browser'
import * as SecureStore from 'expo-secure-store'
import { Web3AuthProvider } from '@web3auth/react-native-sdk'
import web3AuthConfig from './web3authConfig'
export default function App() {
return (
<Web3AuthProvider webBrowser={WebBrowser} storage={SecureStore} config={web3AuthConfig}>
<Screen />
</Web3AuthProvider>
)
}
Props
| Prop | Type | Required | Description |
|---|---|---|---|
webBrowser | IWebBrowser | Yes | In-app browser implementation. Use @toruslabs/react-native-web-browser for bare React Native and expo-web-browser for Expo. |
storage | IStorage | Yes | Persistent key-value storage for session data. Use react-native-encrypted-storage for bare React Native and expo-secure-store for Expo. |
config | Web3AuthContextConfig | Yes | SDK configuration object containing web3AuthOptions. Typically imported from a dedicated web3authConfig.ts file. |
key? | string | No | React reconciler key. Change this value to force the provider to remount with a new configuration (for example, when toggling account abstraction on or off). |
children | React.ReactNode | Yes | Child components that consume the Web3Auth hooks. |
Sign users in
Call connectTo from the useWeb3AuthConnect hook. The SDK opens the authentication provider in an in-app browser and returns control to your app after the redirect.
import { AUTH_CONNECTION, useWeb3AuthConnect } from '@web3auth/react-native-sdk'
function LoginView() {
const { connectTo, loading } = useWeb3AuthConnect()
return (
<View>
<Button
title={loading ? 'Signing in…' : 'Sign in with Google'}
disabled={loading}
onPress={() => connectTo({ authConnection: AUTH_CONNECTION.GOOGLE })}
/>
<Button
title="Sign in with Email"
onPress={() =>
connectTo({
authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
extraLoginOptions: { login_hint: 'user@example.com' },
})
}
/>
</View>
)
}
See the hooks reference and the login usage page for the full connectTo parameter reference.
Use the provider for EVM calls
After the user connects, use useWeb3Auth().provider with ethers or viem. No additional provider setup is needed.
import { useWeb3Auth } from '@web3auth/react-native-sdk'
import { ethers } from 'ethers'
function HomeView() {
const { provider } = useWeb3Auth()
const getAddress = async () => {
const ep = new ethers.BrowserProvider(provider!)
return (await ep.getSigner()).getAddress()
}
const signMessage = async (message: string) => {
const ep = new ethers.BrowserProvider(provider!)
return (await ep.getSigner()).signMessage(message)
}
}
Use the signer for Solana
import { useWeb3Auth } from '@web3auth/react-native-sdk'
import type { TransactionSigner } from '@solana/signers'
import { Connection, PublicKey } from '@solana/web3.js'
function SolanaView() {
const { web3Auth } = useWeb3Auth()
const signer = web3Auth?.signer as TransactionSigner | null
const getAddress = () => String(signer?.address)
const getBalance = async () => {
const connection = new Connection('https://api.testnet.solana.com', 'confirmed')
return connection.getBalance(new PublicKey(getAddress()))
}
}
Advanced configuration
- Account Abstraction (smart accounts)
- Custom authentication
- Whitelabeling and UI customization
- Multi-Factor Authentication (MFA)
- Dapp share
Hooks reference
See the hooks reference for full documentation on all available hooks:
useWeb3Auth, useWeb3AuthConnect, useWeb3AuthDisconnect, useWeb3AuthUser, useWalletUI, useSignatureRequest, useIdentityToken, useEnableMFA, useManageMFA.
Troubleshooting
If you run into Metro bundler errors, see the Metro polyfill troubleshooting guide.