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

Embedded Wallet SDK for React Native

Overview​

The Web3Auth by MetaMask, Embedded Wallet SDK for React Native (@web3auth/react-native-sdk) adds social sign-in and wallet functionality to your iOS and Android apps. Wrap your app in Web3AuthProvider and use React hooks to sign users in, read the wallet connection, and open Wallet Services.

This page covers v10 of the SDK. After sign-in, useWeb3Auth().connection exposes an EIP-1193 ethereumProvider for EVM chains and a Wallet Standard solanaWallet for Solana. Optional entry points add Wagmi hooks (@web3auth/react-native-sdk/wagmi) and Solana hooks (@web3auth/react-native-sdk/solana).

Migrate from an earlier version

See the React Native migration guide to upgrade from any earlier @web3auth/react-native-sdk version.

Requirements​

  • Node.js 22 or later.
  • React Native. The official examples use React Native 0.74 (bare) and Expo SDK 51.
  • For Expo, a development build, because the SDK uses the native module react-native-quick-crypto.
  • iOS: deployment target supported by your React Native version. Sign-in uses ASWebAuthenticationSession.
  • Android: a browser that supports Custom Tabs.

Prerequisites​

Set up your project on the Embedded Wallets dashboard:

  1. Create a project and copy the Client ID.
  2. Choose a custom URL scheme for your app (for example, web3authrnexample) and add the full redirect URL you pass to the SDK (for example, web3authrnexample://auth) to the allowlist.
  3. Configure the chains your app uses, or pass them in code with chains.

See the dashboard setup guide for details.

Install​

1. Install the SDK and its peer packages​

The SDK needs an in-app browser, secure storage, and a native crypto implementation. The packages differ between bare React Native and Expo:

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

Then install react-native-quick-crypto. Pick the version that matches your app:

Your appInstall
React Native 0.75 or later with the New Architecturereact-native-quick-crypto 1.x, react-native-nitro-modules, and react-native-quick-base64 3.x or later
React Native earlier than 0.75, or the old architecturereact-native-quick-crypto 0.7.x (the official examples use ^0.7.6)
npm install react-native-quick-crypto react-native-nitro-modules react-native-quick-base64
Install a working react-native-quick-crypto

@web3auth/react-native-sdk/setup installs react-native-quick-crypto as the global crypto object, and sign-in uses crypto.getRandomValues. The SDK declares react-native-quick-crypto as an optional peer dependency, but if it's missing or its native library fails to load, setup skips it without an error. In our testing on an Android emulator, the SDK then initialized but connectTo failed with TypeError: undefined is not a function in randomBytes.

On an Android emulator with 16 KB memory pages, react-native-quick-crypto 0.7.x failed to load (dlopen failed: empty/missing DT_HASH/DT_GNU_HASH), while 1.x loaded. If your app must run on 16 KB-page devices, use 1.x.

2. Configure Android​

Register your URL scheme on the main activity in android/app/src/main/AndroidManifest.xml so the in-app browser can return to your app. Set android:launchMode="singleTask" and android:exported="true":

android/app/src/main/AndroidManifest.xml
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:exported="true">
<!-- existing MAIN / LAUNCHER intent filter -->
<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>
</activity>
Gradle 9 and @toruslabs/react-native-web-browser

@toruslabs/react-native-web-browser 1.1.0 calls jcenter() in its android/build.gradle. Gradle 9 removed jcenter(), so on React Native versions that use Gradle 9 (for example, 0.84) the Android build fails with Could not find method jcenter(). Until a fixed version is released, replace jcenter() with mavenCentral() in node_modules/@toruslabs/react-native-web-browser/android/build.gradle and persist the change with patch-package.

3. Configure iOS​

Install pods:

cd ios && pod install

4. Configure Expo​

Add your scheme to app.json, then create a development build with npx expo prebuild or EAS Build:

app.json
{
"expo": {
"scheme": "web3authexpoexample"
}
}

Build the redirect URL with expo-linking. Expo Go and development or standalone builds resolve different URLs, so allowlist each URL your app uses:

import Constants, { AppOwnership } from 'expo-constants'
import * as Linking from 'expo-linking'

const redirectUrl =
Constants.appOwnership === AppOwnership.Expo ||
// @ts-expect-error AppOwnership.Guest is missing from the expo-constants typings
Constants.appOwnership === AppOwnership.Guest
? Linking.createURL('web3auth', {})
: Linking.createURL('web3auth', { scheme: 'web3authexpoexample' })

Configure Metro, Babel, and the entry file​

Entry file​

Import @web3auth/react-native-sdk/setup as the first line of your app's entry file. It installs the Buffer, TextEncoder, and crypto globals that the SDK needs.

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

For Solana apps, also import the Solana polyfills described in Solana hooks.

Metro​

withWeb3Auth adds the Node.js module aliases and global shims that the SDK and its dependencies need:

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

const config = getDefaultConfig(__dirname)
module.exports = withWeb3Auth(config)

Babel​

Add @babel/plugin-transform-export-namespace-from. Some SDK dependencies use export * as syntax that the React Native Babel preset doesn't transform.

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

Configure the SDK​

Create a web3authConfig.ts file that exports a Web3AuthContextConfig. chains is optional when you configure chains on the dashboard; chains you pass in code are merged with the dashboard chains and take precedence.

web3authConfig.ts
import { WEB3AUTH_NETWORK, type Web3AuthContextConfig } from '@web3auth/react-native-sdk'

const web3AuthConfig: Web3AuthContextConfig = {
web3AuthOptions: {
clientId: '<YOUR_CLIENT_ID>', // from developer.metamask.io
redirectUrl: 'web3authrnexample://auth', // must be allowlisted on the dashboard
network: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
},
}

export default web3AuthConfig

See Advanced configuration for all web3AuthOptions.

Set up Web3AuthProvider​

Web3AuthProvider is the React context provider that initialises the SDK and makes all hooks available to the component tree.

import * as 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>
)
}

Props​

PropTypeRequiredDescription
webBrowserIWebBrowserYesIn-app browser implementation. Use @toruslabs/react-native-web-browser for bare React Native and expo-web-browser for Expo.
storageEncryptedStorage | SecureStoreYesSecure storage for session data. Use react-native-encrypted-storage for bare React Native and expo-secure-store for Expo.
configWeb3AuthContextConfigYes{ web3AuthOptions } object, typically exported from web3authConfig.ts.
childrenReact.ReactNodeYesComponents that use the Embedded Wallets hooks.

The provider creates a new SDK instance whenever the config.web3AuthOptions object, webBrowser, or storage changes identity. Define the config outside your component or memoize it. To switch configurations at runtime (for example, to toggle account abstraction), pass a new React key to remount the provider.

Sign users in​

Call connectTo from the useWeb3AuthConnect hook. The SDK opens the sign-in flow in an in-app browser and returns to your app through redirectUrl.

import { AUTH_CONNECTION, useWeb3Auth, useWeb3AuthConnect } from '@web3auth/react-native-sdk'
import { ActivityIndicator, Button, View } from 'react-native'

function Screen() {
const { isConnected, isInitializing } = useWeb3Auth()
const { connectTo, loading } = useWeb3AuthConnect()

if (isInitializing) return <ActivityIndicator />
if (isConnected) return <HomeView />

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"
disabled={loading}
onPress={() =>
connectTo({
authConnection: AUTH_CONNECTION.EMAIL_PASSWORDLESS,
extraLoginOptions: { login_hint: 'user@example.com' },
})
}
/>
</View>
)
}

See Sign in and useWeb3AuthConnect for all connectTo parameters.

Make EVM calls​

After sign-in, pass connection.ethereumProvider to viem or ethers:

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

function HomeView() {
const { connection } = useWeb3Auth()

const signMessage = async () => {
const walletClient = createWalletClient({
transport: custom(connection!.ethereumProvider!),
})
const [account] = await walletClient.getAddresses()
return walletClient.signMessage({ account, message: 'Hello' })
}

// ...
}

To use Wagmi hooks instead, see Ethereum hooks (Wagmi).

Make Solana calls​

For Solana chains, wrap your app in SolanaProvider and use the hooks from @web3auth/react-native-sdk/solana. See Solana hooks.

Next steps​

Troubleshooting​

For Metro bundler and polyfill errors, see React Native Metro polyfill issues.