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

# Bundler polyfill issues - React Native Metro

This page documents how to configure Metro to handle Node.js polyfills required by the Embedded Wallets React Native SDK.

## v9 (recommended)

SDK v9 ships a single helper that configures Metro and polyfills automatically. No manual `extraNodeModules` is needed.

### 1. Install the SDK

**npm**

```bash
npm install @web3auth/react-native-sdk
npm install --save-dev @babel/plugin-transform-export-namespace-from

```

**Yarn**

```bash
yarn add @web3auth/react-native-sdk
yarn add --dev @babel/plugin-transform-export-namespace-from

```

**pnpm**

```bash
pnpm add @web3auth/react-native-sdk
pnpm add --save-dev @babel/plugin-transform-export-namespace-from

```

**Bun**

```bash
bun add @web3auth/react-native-sdk
bun add --dev @babel/plugin-transform-export-namespace-from

```

### 2. Entry point, add setup import

Add `import "@web3auth/react-native-sdk/setup"` as the **first line** of your app's entry file:

**Bare React Native**

index.js

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

```

**Expo**

Create `index.ts` and set `"main": "index.ts"` in `package.json`:

index.ts

```ts
import '@web3auth/react-native-sdk/setup' // must be first
import { registerRootComponent } from 'expo'
import App from './App'
registerRootComponent(App)

```

### 3. Update `metro.config.js`

**Bare React Native**

metro.config.js

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

```

**Expo**

metro.config.js

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

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

```

info

Polyfills are not supported with the Expo Go app. Use a custom dev client or an EAS build and run `npx expo prebuild` to generate native code.

`withWeb3Auth` applies all required polyfill aliases (`crypto`, `stream`, `buffer`, and so on) internally. You can still add custom `sourceExts` or other resolver options after calling it.

### 4. Update `babel.config.js`

Add `@babel/plugin-transform-export-namespace-from`. Without it, Metro fails to parse some SDK internal re-exports.

**Bare React Native**

babel.config.js

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

```

**Expo**

babel.config.js

```js
module.exports = function (api) {
  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    plugins: ['@babel/plugin-transform-export-namespace-from'],
  }
}

```

---

## v8 (legacy manual setup)

If you are still using `@web3auth/react-native-sdk@^8.x`, follow the manual polyfill steps below. We recommend [upgrading to v9](/embedded-wallets/migration-guides/react-native/).

### 1. Install polyfill packages

**npm**

```bash
npm install --save empty-module readable-stream crypto-browserify react-native-get-random-values buffer process

```

**Yarn**

```bash
yarn add empty-module readable-stream crypto-browserify react-native-get-random-values buffer process

```

**pnpm**

```bash
pnpm add empty-module readable-stream crypto-browserify react-native-get-random-values buffer process

```

**Bun**

```bash
bun add empty-module readable-stream crypto-browserify react-native-get-random-values buffer process

```

### 2. `metro.config.js` (v8)

**Bare React Native**

metro.config.js

```js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
const defaultConfig = getDefaultConfig(__dirname)

const config = {
  resolver: {
    extraNodeModules: {
      assert: require.resolve('empty-module'),
      http: require.resolve('empty-module'),
      https: require.resolve('empty-module'),
      os: require.resolve('empty-module'),
      url: require.resolve('empty-module'),
      zlib: require.resolve('empty-module'),
      path: require.resolve('empty-module'),
      crypto: require.resolve('crypto-browserify'),
      stream: require.resolve('readable-stream'),
    },
    sourceExts: [...defaultConfig.resolver.sourceExts, 'svg'],
  },
}

module.exports = mergeConfig(defaultConfig, config)

```

**Expo**

metro.config.js

```js
const { getDefaultConfig } = require('expo/metro-config')
const config = getDefaultConfig(__dirname)

config.resolver.extraNodeModules = {
  assert: require.resolve('empty-module'),
  http: require.resolve('empty-module'),
  https: require.resolve('empty-module'),
  os: require.resolve('empty-module'),
  url: require.resolve('empty-module'),
  zlib: require.resolve('empty-module'),
  path: require.resolve('empty-module'),
  crypto: require.resolve('crypto-browserify'),
  stream: require.resolve('readable-stream'),
  buffer: require.resolve('buffer'),
}

module.exports = config

```

### 3. `globals.js` and entry point (v8)

Create `globals.js` at your project root:

globals.js

```js
global.Buffer = require('buffer').Buffer
global.location = { protocol: 'file:' }
global.process.version = 'v16.0.0'
if (!global.process.version) {
  global.process = require('process')
}
process.browser = true

```

Then import it in your entry point:

index.js

```js
import { AppRegistry } from 'react-native'
import './globals'
import 'react-native-get-random-values'
import App from './App'
import { name as appName } from './app.json'
AppRegistry.registerComponent(appName, () => App)

```
