web3 and 0x.js were designed to work in a web browser and in node.js . react-native is missing several libraries that node.js includes (like crypto ). Also, metro , the react-native dependency bundler, does some up-front magic to gather a list of dependencies, which makes dynamically constructed require statements impossible.

To get things working, there was 1 big decision to make:

web3 1.x or 0.20.x?

And 2 bugs to fix:

How to get beyond unable to resolve module errors.

errors. How to overcome the Cannot find variable: self error.

TLDR

Several node.js libraries are missing in react-native and isomorphic-fetch doesn’t work well with react-native . To get it working, follow these steps:

npm i -S web3@0.20.5 (Do not use web3@1.0 ).

(Do not use ). npm i -S abec/node-libs-react-native .

. Add the following to rn-cli.config.js :

const extraNodeModules = require(“node-libs-react-native”);

module.exports = {

extraNodeModules

};

Add the following to the top of your root index.js file:

import “node-libs-react-native/globals”;

Add the following config to your package.json under the scripts section:

“prepare”: “npm run patch”,

“patch”: “find ./node_modules -name fetch-npm-browserify.js -print -exec sed -i.bk 's/self/global/g' {} \\;”

Problem: Web3 1.0 vs. 0.20.x

The way web3 version 1.0 manages dependencies differs greatly from 0.20.x . It splits itself up into several packages and ties them together using lerna. Also, some of dependencies are dynamically constructed, which conflicts with metro ’s dependency gathering process.

Solution: Use 0.20.x

Install web3 version 0.20.5 :

npm i -S web3@0.20.5

NOTE: The latest 1.x line seems to be working at first glance. 0x is still using 0.20.x though.

Problem: Unable To Resolve Module Errors

If you try to use web3 or 0x.js in react-native , the first error you’ll encounter is:

bundling failed: Error: Unable to resolve module `crypto` from `…`: Module does not exist in the module map

react-native doesn’t include a crypto library (as well as several other libraries).

Solution: Use node-libs-react-native

Polyfills for the required modules exist and are aggregated in a library called node-libs-react-native . This library includes everything necessary to get web3 working, with the exception of vm . Without vm the following error comes up:

error: bundling failed: Error: Unable to resolve module `vm` from `.../node_modules/asn1.js/lib/asn1/api.js`: Module does not exist in the module map

vm is actually optional in asn1 , but metro pulls it in when it builds its dependency list. The build process errors accordingly. So, I forked that github repo and added vm-browserify .

Here are steps to get this working:

Run npm i -S abec/node-libs-react-native . Add the following to rn-cli.config.js :

const extraNodeModules = require(“node-libs-react-native”);

module.exports = {

extraNodeModules

};

3. Add the following to the top of your root index.js file:

import “node-libs-react-native/globals”;

Problem: Cannot Find Variable: Self

0x connect has a dependency on isomorphic-fetch , which does not work in react-native . When included, it throws this error:

Cannot find variable: self

isomorphic-fetch includes implementations for browser and node.js . The browser implementation, which is the one included when using react-native , has the following code:

// the whatwg-fetch polyfill installs the fetch() function

// on the global object (window or global)

//

// Return that as the export for use in Webpack, Browserify etc. require(‘whatwg-fetch’);

module.exports = self.fetch.bind(self);

react-native has no sense of self and will not be able to include this library.

Solution: Edit The File Before Running (Best)

The fetch-npm-browserify.js file can be modified to replace self with global :

sed -i.bk ‘s/self/global/g’ ./node_modules/@0xproject/connect/node_modules/isomorphic-fetch/fetch-npm-browserify.js

To make this part of your build process, add the following config to your package.json under the scripts section:

“prepare”: “npm run patch”,

“patch”: “find ./node_modules -name fetch-npm-browserify.js -print -exec sed -i.bk 's/self/global/g' {} \\;”

In the long term, this will probably be fixed by the 0x community.

Another Solution: Replace isomorphic-fetch With A Modified Implementation (Not Great)

The dependency management system for react-native can be hacked using rn-nodeify to replace a dependency across all other dependencies. You can replace isomorphic-fetch with your own version using this method. I thought this was even more hacky than the above solution, so I decided against it.

References