Web3.js: web3 import in react-native

Created on 6 Sep 2017  路  39Comments  路  Source: ChainSafe/web3.js

// Versions:
"web3": "1.0.0-beta.18"
"react-native": "0.46.4"
// Error:
Bundling `index.android.js`  0.0% (0/1110), failed.
Error: EISDIR: illegal operation on a directory, read
    at Object.fs.readSync (fs.js:681:18)
    at Object.readSync (ProjectName/node_modules/graceful-fs/polyfills.js:138:28)
    at tryReadSync (fs.js:542:20)
    at Object.fs.readFileSync (fs.js:585:19)
    at Module._readSourceCode (ProjectName/node_modules/metro-bundler/build/node-haste/Module.js:205:29)
    at Module._getCacheProps (ProjectName/node_modules/metro-bundler/build/node-haste/Module.js:395:29)
    at Module._readFromTransformCache (ProjectName/node_modules/metro-bundler/build/node-haste/Module.js:345:29)
    at Module.readCached (ProjectName/node_modules/metro-bundler/build/node-haste/Module.js:332:19)
    at ResolutionRequest.preprocessModule (ProjectName/node_modules/metro-bundler/build/node-haste/DependencyGraph/ResolutionRequest.js:380:27)
    at ResolutionRequest._preprocessPotentialDependencies (ProjectName/node_modules/metro-bundler/build/node-haste/DependencyGraph/ResolutionRequest.js:364:27)

Once I import web3 in my project I get this error, not sure how to fix it, ideas?

Most helpful comment

I created a step-by-step simple guide on how I set up web3.js with Create React Native App:

https://gist.github.com/dougbacelar/29e60920d8fa1982535247563eb63766

All 39 comments

I'm getting the same error even with version 0.20.2

"react": "16.0.0-alpha.12",
"react-native": "0.48.3",
"web3": "^0.20.2"

@binhnd-socicom forgot I opened this, so the problem was that the react-native packager doesn't come with some node built in modules, you need to install node-libs-browser and then add to the root of your project:

// rn-cli.config.js
const extraNodeModules = require('node-libs-browser')

module.exports = {
  extraNodeModules
}

@flaviocarvalho can you tell how to fix this. I tried this

//rn-cli.config.js
const extraNodeModules = require('node-libs-browser');
module.exports = {
  extraNodeModules
}
///App.js
....
require('./rn-cli.config');
....

but I am getting error require.resolve is not a function in require.resolve('/assert')

@TonyFrancis You don't need to import the config on your app, it's a special filename that's gonna be used to configure your rn packager

@flaviocarvalho I tried them I get error Requiring module "react-native-crypto/index.js" which threw an exception: TypeError: undefined is not an object(evaluating 'RNRandomBytes.seed')
I am using create-react-native-app

@TonyFrancis You might need to eject then, try with eject, and worst case scenario try react-native init

@flaviocarvalho It didn't worked

I created a step-by-step simple guide on how I set up web3.js with Create React Native App:

https://gist.github.com/dougbacelar/29e60920d8fa1982535247563eb63766

@dougbacelar thanks it helped.

@dougbacelar now when I try web3.eth.accounts.create I get error Unknown module crypto. CAn you help me ?

@flaviocarvalho Thank you for your instructions. But I get the following error.
Unable to resolve module crypto from path/to/module/node_modules/web3-eth-accounts/src/index.js: Modules does not exist in the module map.

As I understand the sub-module's mapping is not carried forward to dist folder.

Can you please help.

Hi,
Using [email protected]
[email protected]
I have this error:

Bundling `index.js`  [development, non-minified]  98.7% (1059/1066), failed.
error: bundling failed: Error: require() must have a single string literal argument: /Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/web3-eth-accounts/node_modules/eth-lib/lib/bytes.js:8
    at pushDependency (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/metro-bundler/src/JSTransformer/worker/extract-dependencies.js:44:13)
    at CallExpression (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/metro-bundler/src/JSTransformer/worker/extract-dependencies.js:59:9)
    at NodePath._call (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/mokhtarbacha/Documents/workingMobileAppRNodify3/node_modules/babel-traverse/lib/index.js:114:17)

@TonyFrancis
Whats the error you are getting? I will create a repository with both working together soon. Maybe that will help you

@TonyFrancis I'm getting the require() must have a single string literal argument. It's related to dynamic import.
https://github.com/facebook/metro-bundler/issues/65
https://github.com/facebook/react-native/issues/16216
And it's ok for create a repo

i have this issue too. i ended up patching modules myself and now it compiles. I'll test to see if anything was affected in web3

there are two files to patch

node_modules/eth-lib/lib/bytes.js and node_modules/web3-eth-accounts/node_modules/eth-lib/bytes.js

instead of

require("c" + "rypto")

i wrote:

require("crypto")

My problem went away when I used web3@^0.19.1 and added "react-native" section to package.json. Hope it helps someone.

"react-native": {
"zlib": "browserify-zlib",
"console": "console-browserify",
"constants": "constants-browserify",
"crypto": "react-native-crypto",
"dns": "dns.js",
"net": "react-native-tcp",
"domain": "domain-browser",
"http": "react-native-http",
"https": "https-browserify",
"os": "react-native-os",
"path": "path-browserify",
"querystring": "querystring-es3",
"fs": "react-native-level-fs",
"_stream_transform": "readable-stream/transform",
"_stream_readable": "readable-stream/readable",
"_stream_writable": "readable-stream/writable",
"_stream_duplex": "readable-stream/duplex",
"_stream_passthrough": "readable-stream/passthrough",
"dgram": "react-native-udp",
"stream": "stream-browserify",
"timers": "timers-browserify",
"tty": "tty-browserify",
"vm": "vm-browserify"
},

@KSanthanam yes, the old version doesn't have this issue. it's the new version 1.x which has the problem

@azat-co Yes. So I was forced to go back to [email protected]. Sad :(

@azat-co's patch above worked for me too and using [email protected]. I was able to compile and get latest block right after.

web3.eth.getBlock('latest').then(console.log)

5:55:05 PM: Finished building JavaScript bundle in 6010ms
5:55:07 PM: Running app on Android SDK built for x86 in development mode

5:55:08 PM: Object {
5:55:08 PM: "difficulty": "3570652219",
5:55:08 PM: "extraData": "0x4554482e45544846414e532e4f52472d3132383643423442",
5:55:08 PM: "gasLimit": 4712394,
5:55:08 PM: "gasUsed": 239606,
5:55:08 PM: "hash": "0xddf88973e56d96f3e97f7098e82f52d0a70c00a81afae253e805ae5004c04835",
5:55:08 PM: "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
5:55:08 PM: "miner": "0xbbF5029Fd710d227630c8b7d338051B8E76d50B3",
5:55:08 PM: "mixHash": "0xc35ec20af3df0b4e13703c74dac3339ba8846a6aafe50bc27c177acbf05d15cb",
5:55:08 PM: "nonce": "0x5ff4a142ea0daccc",
5:55:08 PM: "number": 2412642,
5:55:08 PM: "parentHash": "0xb5049d4c8056aff5fdd42f4541bfcbfbddde458b1de5080e0da31e7c604aaee6",
5:55:08 PM: "receiptsRoot": "0xd9bb38965f4d5b1a3b44c2888f5c949fd65f2689c048c8aa8218c91b2ea1c105",
5:55:08 PM: "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
5:55:08 PM: "size": 1765,
5:55:08 PM: "stateRoot": "0x5d4f105fcf237e6b86210535754e4a26df0afe1b004db1216fa31a608c198f74",
5:55:08 PM: "timestamp": 1515279263,
5:55:08 PM: "totalDifficulty": "7355460463617464",
5:55:08 PM: "transactions": Array [
5:55:08 PM: "0x0ca3964f34a954a225c8862cd9c6561bfe6c7b57ebedc7d9cde358f9a06c7ab9",
5:55:08 PM: "0xe09d137ff15b3f521d3755cbd83286cf58d1d11e8caf039f85d69fcd722cf008",
5:55:08 PM: "0x29faf2430cfe6eae86dde3aeff4ebd309c3753a122b314645c562e65feeda396",
5:55:08 PM: "0x79e228447d35df3887626778145509ccc05d50ea6fa99f284d11846827c51862",
5:55:08 PM: "0xc71b1b501036439f9ae1933d51984ad08a912d6fd29c477d715fe05f9d39ae1b",
5:55:08 PM: "0x26da32ca38333fc7473adf7cc1b2afef48a08d1f5df1b7a89ec1e32eb0dc7fca",
5:55:08 PM: "0x181a3975912160cb7a1d9093661cadc2c6c31ba422238053b33ce4e1820ef68a",
5:55:08 PM: "0x036acc2f4036be7eb1f8649acf8d356797422a447b86901050eb75eb42336b62",
5:55:08 PM: "0xbda6af8e3ddba44ddc7a49bde005b47c2824991b7f0c3333fdbf57030d9068ef",
5:55:08 PM: ],
5:55:08 PM: "transactionsRoot": "0x6243406b2d47747e4ba236916854fdb31e346f207296734ed8f28a40561dc1c0",
5:55:08 PM: "uncles": Array [],
5:55:08 PM: }

I was able to make it work using web3 version 0.20.x, in case it helps someone, as a workaround I created a babel preset for react-native to use it out of the box.

https://github.com/agrcrobles/babel-preset-react-native-web3

Edit: Looks like this issue it's cloned from https://github.com/ethereum/web3.js/issues/1108 and https://github.com/ethereum/web3.js/issues/576

@azat-co The patch works. But will it be overwritten if I update node modules?

https://github.com/markspereira/react-native-web3-boilerplate I managed to get web3 1.0.0 working. For account creation I use 'ethereumjs-wallet' as it doesn't work with the web3 1.0.0 on react-native and that pretty much covers everything you would want to do.

@markspereira -- do you think this will work with CRNA?

@ortonomy I haven't tried but I don't see why not.

@ortonomy maybe this can help you

@dougbacelar -- it actually runs fine on my mac, but my colleagues running on different macs are starting to get this error: Error: No "crypto" object available. This Browser doesn't support generating secure random bytes -- and I can't work out why. It runs FINE on my computer...

I think this question should be on https://ethereum.stackexchange.com/

i got web3 1.2.1 up and running with [email protected] and [email protected]

react-native init APPNAME
npm i --save react-native-crypto
npm i --save react-native-randombytes
cd ios/
pod install
cd ..
npm i --save-dev rn-nodeify@latest
./node_modules/.bin/rn-nodeify --install
npm i --save node-libs-browser
npm i base-64

modify APPNAME/metro.config.js to read:

const extraNodeModules = require('node-libs-browser');

module.exports = {
  resolver: {
    extraNodeModules,
  },
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

modify shim.js to read:

import {decode, encode} from 'base-64'

if (!global.btoa) global.btoa = encode
if (!global.atob) global.atob = decode

if (typeof __dirname === 'undefined') global.__dirname = '/'
if (typeof __filename === 'undefined') global.__filename = ''
if (typeof process === 'undefined') {
  global.process = require('process')
} else {
  const bProcess = require('process')
  for (var p in bProcess) {
    if (!(p in process)) {
      process[p] = bProcess[p]
    }
  }
}

process.browser = false
if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer

if (typeof location === 'undefined') global.location = { port: 80, protocol: 'https:' }
const isDev = typeof __DEV__ === 'boolean' && __DEV__
process.env['NODE_ENV'] = isDev ? 'development' : 'production'
if (typeof localStorage !== 'undefined') {
  localStorage.debug = isDev ? '*' : ''
}

// If using the crypto shim, uncomment the following line to ensure
// crypto is loaded first, so it can populate global.crypto
require('crypto')

import './shim' **in App.js

npm i --save web3

xed -b ios **open and build through xcode for the first time.

Hi @ioitiki i follow setup web of you, but when run then return error:
Secure random number generation is not supported by this browser. User Chrome, Firefox or Internet Explorer 11.

Environment

react: 16.8.3
react-native: 0.59.8
web3: 1.1.0-beta.55

Hi @ioitiki i follow setup web of you, but when run then return error:
Secure random number generation is not supported by this browser. User Chrome, Firefox or Internet Explorer 11.

Environment

react: 16.8.3
react-native: 0.59.8
web3: 1.1.0-beta.55

@bachlongkocanh try the new procedure i just posted. the auto-linking with pod file should fix that problem for you!

If you are running windows change a few steps in @ioitiki answer.

react-native init APPNAME
npm i --save react-native-crypto
npm i --save react-native-randombytes
react-native link react-native-randombytes
npm i --save-dev rn-nodeify@latest
rn-nodeify --install
npm i --save node-libs-browser
npm i base-64

Then modify the files like he did. Then do...

import './shim' **in App.js
npm i --save web3
react-native run-android

Once I did this I was able to log the latest block using...

const Web3 = require('web3');
const web3 = await new Web3(
    new Web3.providers.HttpProvider('https://mainnet.infura.io/')
);
web3.eth.getBlock('latest').then(console.log);

UPDATE

if i try to install [email protected] i get the following error:
Error: Invalid JSON RPC response: ""

so in order to get everything working with the newest react versions i rolled web3 back to 1.0.0-beta.55 and everything is good! :D

If you are running windows change a few steps in @ioitiki answer.

react-native init APPNAME
npm i --save react-native-crypto
npm i --save react-native-randombytes
react-native link react-native-randombytes
npm i --save-dev rn-nodeify@latest
rn-nodeify --install
npm i --save node-libs-browser
npm i base-64

Then modify the files like he did. Then do...

import './shim' **in App.js
npm i --save web3
react-native run-android

Once I did this I was able to log the latest block using...

const Web3 = require('web3');
const web3 = await new Web3(
    new Web3.providers.HttpProvider('https://mainnet.infura.io/')
);
web3.eth.getBlock('latest').then(console.log);

what about?

const wallet = web3.eth.account.create();

edit1: Hi @petercooke536 i have been working with react native and web3js and i have found that you will need to edit the shim.js and also you will need to run ./node_modules/.bin/rn-nodeify --install after you have cloned the project to a new folder

https://ethereum.stackexchange.com/

I don't think you're right,please open the issues

Hi @Lloyd1229 i am currently working in a react native project that uses web3js and i can confirm that the method shown by @ioitiki works on an android emulator or usb android emulator i havnt tested it with ios so i cant say the same, but what i have found is that it will have some weird interaction with @react-navigation especially its dependency react-native-gesture-handler when you put import 'react-native-gesture-handler'; in the main entry file of the app. I think its because of the way import './shim'; line interacts with that line.

Hi @Lloyd1229 i am currently working in a react native project that uses web3js and i can confirm that the method shown by @ioitiki works on an android emulator or usb android emulator i havnt tested it with ios so i cant say the same, but what i have found is that it will have some weird interaction with @react-navigation especially its dependency react-native-gesture-handler when you put import 'react-native-gesture-handler'; in the main entry file of the app. I think its because of the way import './shim'; line interacts with that line.

Hello, can you tell me what your version is and the installation process of web3.js?

i got web3 1.2.1 up and running with [email protected] and [email protected]

react-native init APPNAME
npm i --save react-native-crypto
npm i --save react-native-randombytes
cd ios/
pod install
cd ..
npm i --save-dev rn-nodeify@latest
./node_modules/.bin/rn-nodeify --install
npm i --save node-libs-browser
npm i base-64

modify APPNAME/metro.config.js to read:

const extraNodeModules = require('node-libs-browser');

module.exports = {
  resolver: {
    extraNodeModules,
  },
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

modify shim.js to read:

import {decode, encode} from 'base-64'

if (!global.btoa) global.btoa = encode
if (!global.atob) global.atob = decode

if (typeof __dirname === 'undefined') global.__dirname = '/'
if (typeof __filename === 'undefined') global.__filename = ''
if (typeof process === 'undefined') {
  global.process = require('process')
} else {
  const bProcess = require('process')
  for (var p in bProcess) {
    if (!(p in process)) {
      process[p] = bProcess[p]
    }
  }
}

process.browser = false
if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer

if (typeof location === 'undefined') global.location = { port: 80, protocol: 'https:' }
const isDev = typeof __DEV__ === 'boolean' && __DEV__
process.env['NODE_ENV'] = isDev ? 'development' : 'production'
if (typeof localStorage !== 'undefined') {
  localStorage.debug = isDev ? '*' : ''
}

// If using the crypto shim, uncomment the following line to ensure
// crypto is loaded first, so it can populate global.crypto
require('crypto')

import './shim' **in App.js

npm i --save web3

xed -b ios **open and build through xcode for the first time.

its same as this and the current version is "web3": "^1.2.11" and "react-native": "0.63.2" i havent done any testing with ios but when setting up a react-native app with web3js you can follow the above instruction its working for me

Hi @Lloyd1229 i am currently working in a react native project that uses web3js and i can confirm that the method shown by @ioitiki works on an android emulator or usb android emulator i havnt tested it with ios so i cant say the same, but what i have found is that it will have some weird interaction with @react-navigation especially its dependency react-native-gesture-handler when you put import 'react-native-gesture-handler'; in the main entry file of the app. I think its because of the way import './shim'; line interacts with that line.

What is the weird interaction react-native-gesture-handler after import shim.js? I am trying to import web3 into RN 0.63.2 app which has extensive use of react-navigation and react-native-gesture-handler/react-native-reanimated. Is any module broken after import shim.js?. Many thanks.

hi @emclab so currently i havent test my app on ios platform and have not put this line import 'react-native-gesture-handler'; when i was starting my project the shim.js was interacting with the react-native-gesture-handler and giving the error of device not capable of true random generation. I have now added the import line after import 'shim.js'; and no error has been shown so i am not 100% sure what that interaction was i hope i havent scared you by my comment. I will update this after i have tested my app on an iso platform. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FradSer picture FradSer  路  3Comments

dhl picture dhl  路  3Comments

nivida picture nivida  路  3Comments

ragnu picture ragnu  路  3Comments

xpepermint picture xpepermint  路  3Comments