ethers.js icon indicating copy to clipboard operation
ethers.js copied to clipboard

React-Native Issue

Open SyedImam1998 opened this issue 2 years ago • 12 comments

Ethers Version

^6.3.0

Search Terms

No response

Describe the Problem

Hi Team,

I am currently working on react-native project and i followed the guide that was provided here( https://docs.ethers.org/v5/cookbook/react-native/#:~:text=To%20use%20ethers%20in%20React,the%20security%20of%20your%20application.) But still i am getting this error:

Code Snippet

No response

Contract ABI

No response

Errors

error: Error: Unable to resolve module net from C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\ethers\lib.commonjs\providers\provider-ipcsocket.js: net could not be found within the project or in these directories:
  node_modules\ethers\node_modules
  node_modules
  2 | Object.defineProperty(exports, "__esModule", { value: true });
  3 | exports.IpcSocketProvider = void 0;
> 4 | const net_1 = require("net");
    |                        ^
  5 | const provider_socket_js_1 = require("./provider-socket.js");
  6 | // @TODO: Is this sufficient? Is this robust? Will newlines occur between
  7 | // all payloads and only between payloads?
    at ModuleResolver.resolveDependency (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\node-haste\DependencyGraph\ModuleResolution.js:162:15)
    at DependencyGraph.resolveDependency (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\node-haste\DependencyGraph.js:260:43)
    at Object.resolve (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\lib\transformHelpers.js:177:21)
    at Graph._resolveDependencies (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\DeltaBundler\Graph.js:432:35)
    at Graph._processModule (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\DeltaBundler\Graph.js:218:38)
    at async Graph._addDependency (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\DeltaBundler\Graph.js:314:20)
    at async Promise.all (index 19)
    at async Graph._processModule (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\DeltaBundler\Graph.js:263:5)
    at async Graph._addDependency (C:\Users\ACER\Desktop\carbon-tracker\carbontracker\node_modules\metro\src\DeltaBundler\Graph.js:314:20)
    at async Promise.all (index 7)

Environment

No response

Environment (Other)

No response

SyedImam1998 avatar Apr 25 '23 05:04 SyedImam1998

@SyedImam1998 have you been able to resolve this? I'm having same errors.

beansgum avatar May 04 '23 06:05 beansgum

I have a fix coming out for this soon. In the mean time, if you npm install @types/node it should resolve this.

ricmoo avatar May 04 '23 09:05 ricmoo

@SyedImam1998 have you been able to resolve this? I'm having same errors.

Hey mate I moved to version ethers 5.7 here they have cookbook for react native https://docs.ethers.org/v5/cookbook/

SyedImam1998 avatar May 04 '23 14:05 SyedImam1998

npm install @types/node

@ricmoo doesn't work for me, the error is still there

vladbars avatar May 04 '23 21:05 vladbars

I have a fix coming out for this soon. In the mean time, if you npm install @types/node it should resolve this.

It doesn't solve the problem

artureg avatar May 08 '23 12:05 artureg

The problem here is a simple. React native (at least version 0.71 current one) do not support "exports" field https://github.com/facebook/metro/issues/670#issuecomment-1434510835 React-native try to grab "browser" field for root import https://facebook.github.io/metro/docs/configuration#resolvermainfields and as browser field do not contain root import it fallback to "main" field that loads the nodejs (commonjs) version.

There are a multiple solutions:

  • Instead of ethers import the ethers/lib.esm/index.js (not good as thats internal and can be changed in future)
  • Implement on metro.config.js "resolveRequest" the will replace ethers with ethers/lib.esm/index.js
  • Help ethers.js developers implement special entry point "react-native" in package.json that used by default on react-native. That also can include special "shim" for react-native or different implementation as we on different entry point. Best one

Systerr avatar May 08 '23 13:05 Systerr

If someone has resolved the v6 issues, please contact me too, so I can include instructions. I’m considering a dedicated rn package too, if people are interested.

ricmoo avatar May 08 '23 13:05 ricmoo

In my setup (expo 48). And it not deep tested (can be a wrong solution)

  1. Create a metro.config.js

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');

// eslint-disable-next-line no-undef
const config = getDefaultConfig(__dirname);

config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (moduleName === 'ethers') {
    return context.resolveRequest(context, 'ethers/lib.esm/index.js', platform);
  }
  return context.resolveRequest(context, moduleName, platform);
};

module.exports = config;

  1. Prepare environment (shims) https://docs.ethers.org/v5/cookbook/react-native/ (do NOT install get-random-values)
npm i @ethersproject/shims
  1. As get-random-values v2.1 (latest for now) can't be used on expo 48+ (they are deprecated some module that used by get-random-values and second time of use get-random-values will fail). We should implement it based on latest "expo-crypto"
npx expo install expo-crypto

Create file "crypt-shim.js"

import { getRandomValues as expoCryptoGetRandomValues } from 'expo-crypto';

class Crypto {
  getRandomValues = expoCryptoGetRandomValues;
}

const webCrypto = typeof crypto !== 'undefined' ? crypto : new Crypto();

(() => {
  if (typeof crypto === 'undefined') {
    Object.defineProperty(window, 'crypto', {
      configurable: true,
      enumerable: true,
      get: () => webCrypto,
    });
  }
})();

  1. Glue it together.

Inside App.js (or any entry point for you)

import './crypto-shim';
import '@ethersproject/shims';
  1. In any file use ethers as usual
import { ethers } from 'ethers';
const randomWallet = ethers.Wallet.createRandom();
console.log(randomWallet);

Hope that helps.

Systerr avatar May 08 '23 14:05 Systerr

Tried it and it worked for an example code but when we tried to get balance from a provider, we couldn't get a response.

Rhouka avatar May 10 '23 08:05 Rhouka

If you still have that issue, or if some one else have it.

This happens becouse react native don't use the node core modules, like crypto, net, buffer etc. all this modules will return allways undifined, there are there are several ways to fix this, you can use the package rn-nodefy, as @heroims comments here (https://github.com/heroims)#https://github.com/ethers-io/ethers.js/discussions/3905#discussioncomment-5343065 or you can do this by your self using with the library node-libs-react-native.

  1. install the library in your app npm i node-libs-react-native --safe

  2. Configure your metro.config.js to use this modules:

module.exports = {
  // another configurations
  resolver: {
    extraNodeModules: require('node-libs-react-native')
  }
};
  1. You have to name the the global variables in your app, like process etc, to do this just add this line in the top of your index.js
import 'node-libs-react-native/globals';

This should make your react--native app compatible with node core modules, another thing to mention is that when I was setting this up, even if I was doing it with rn-nodefy, I had an error with some react hooks and also had the following error in a FlatList:

flatListError

This happens because react native has conflict with the plugin @babel/plugin-proposal-class-properties so to fix this, go to your babel.config.js, and set it like this:

module.exports = {
  plugins: ['react-native-reanimated/plugin'],
  presets: ['module:metro-react-native-babel-preset'],
  overrides: [
    {
      test: './node_modules/ethers',
      plugins: [
        '@babel/plugin-proposal-private-property-in-object',
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-proposal-private-methods'
      ]
    }
  ]
};

With this configuration you only apply the plugins only for ethers and not for all the modules.

JorgeLpzGnz avatar May 19 '23 21:05 JorgeLpzGnz

it's solved the issue for me https://github.com/ethers-io/ethers.js/issues/4307#issuecomment-1673620848 Also thank you JorgeLpzGnz

vladbars avatar Aug 22 '23 15:08 vladbars

If you still have that issue, or if some one else have it.

This happens becouse react native don't use the node core modules, like crypto, net, buffer etc. all this modules will return allways undifined, there are there are several ways to fix this, you can use the package rn-nodefy, as @heroims comments here (#3905 (comment) or you can do this by your self using with the library node-libs-react-native.

1. install the library in your app
   `npm i node-libs-react-native --safe`

2. Configure your metro.config.js to use this modules:
module.exports = {
  // another configurations
  resolver: {
    extraNodeModules: require('node-libs-react-native')
  }
};
3. You have to name the the global variables in your app, like process etc, to do this just add this line in the top of your index.js
import 'node-libs-react-native/globals';

This should make your react--native app compatible with node core modules, another thing to mention is that when I was setting this up, even if I was doing it with rn-nodefy, I had an error with some react hooks and also had the following error in a FlatList: flatListError

This happens because react native has conflict with the plugin @babel/plugin-proposal-class-properties so to fix this, go to your babel.config.js, and set it like this:

module.exports = {
  plugins: ['react-native-reanimated/plugin'],
  presets: ['module:metro-react-native-babel-preset'],
  overrides: [
    {
      test: './node_modules/ethers',
      plugins: [
        '@babel/plugin-proposal-private-property-in-object',
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-proposal-private-methods'
      ]
    }
  ]
};

With this configuration you only apply the plugins only for ethers and not for all the modules.

Please, how to merge this configuration

resolver: { extraNodeModules: require('node-libs-react-native') }

in metro.config as my file looks like this one?

const config = {}; module.exports = mergeConfig(getDefaultConfig(__dirname), config);

marcilio-souza avatar Jun 13 '24 18:06 marcilio-souza