Skip to content

Instantly share code, notes, and snippets.

@dougbacelar
Last active October 19, 2023 21:12
Star You must be signed in to star a gist
Save dougbacelar/29e60920d8fa1982535247563eb63766 to your computer and use it in GitHub Desktop.
How to set up web3.js (Ethereum JS API) with Create React Native App

How to set up web3.js with CRNA

This is a simple guide to get you started with using the Ethereum Javascript API (web3.js) with the Create React Native App project. This is not an in-depth guide.

TL;DR

If you are lazy and just want to get started, I have this project ready for you. It should work out-of-the-box.

Installation guide

  1. Make sure you have Node version 6 or later installed, if not, get it on the Node website

    node --version

  2. Install Create React Native App

    npm install -g create-react-native-app

  3. Use create-react-native-app to create the project boilerplate

    create-react-native-app my-app

  4. Install node-libs-browser

    npm install --save node-libs-browser

  5. Create a file called rn-cli.config.js on the root of the project and add the following code into it:

    const extraNodeModules = require('node-libs-browser');
    
    module.exports = {
      extraNodeModules,
    };
  6. Create a file called global.js on the root of the project and add the following code into it:

    // Inject node globals into React Native global scope.
    global.Buffer = require('buffer').Buffer;
    global.process = require('process');
    
    if (typeof btoa === 'undefined') {
      global.btoa = function (str) {
        return new Buffer(str, 'binary').toString('base64');
      };
    }
    
    if (typeof atob === 'undefined') {
      global.atob = function (b64Encoded) {
        return new Buffer(b64Encoded, 'base64').toString('binary');
      };
    }
  7. Import the global.js file into your App.js file

    import './global';
  8. Install babel-preset-es2015

    npm install --save-dev babel-cli babel-preset-es2015

  9. Now we can install the web3.js api

    npm install --save web3

  10. Require the API in your App.js file

    const Web3 = require('web3');
  11. Add the following code inside your React component in App.js to get started with consuming the API. The code will print information of the latest block on the console.

    componentWillMount() {
      const web3 = new Web3(
        new Web3.providers.HttpProvider('https://mainnet.infura.io/')
      );
    
      web3.eth.getBlock('latest').then(console.log)
    }
  12. Test it

    npm start

    or

    npm run ios

    or

    npm run android

For more examples on the API usage, visit the web3.js documentation.

For a project with all this setup ready, check out my repo.

@ZeeshanAhmadKhalil
Copy link

Please do it for the newer version of react-native!

@ZeeshanAhmadKhalil
Copy link

i got web3 up and running with RN59 and React 16.8

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
./node_modules/.bin/rn-nodeify --install
npm i --save node-libs-browser

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:

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

react-native run-ios

There is no shim.js file in my app!

@rohankeskar19
Copy link

I'm getting the following error

Validation Warning:

  Unknown option "extraNodeModules" with value {"_stream_duplex": "D:\\react-native\\myapp\\node_modules\\readable-stream\\duplex.js", "_stream_passthrough": "D:\\react-native\\myapp\\node_modules\\readable-stream\\passthrough.js", "_stream_readable": "D:\\react-native\\myapp\\node_modules\\readable-stream\\readable.js", "_stream_transform": "D:\\react-native\\myapp\\node_modules\\readable-stream\\transform.js", "_stream_writable": "D:\\react-native\\myapp\\node_modules\\readable-stream\\writable.js", "assert": "D:\\react-native\\myapp\\node_modules\\assert\\assert.js", "buffer": "D:\\react-native\\myapp\\node_modules\\buffer\\index.js", "child_process": null, "cluster": null, "console": "D:\\react-native\\myapp\\node_modules\\console-browserify\\index.js", "constants": "D:\\react-native\\myapp\\node_modules\\constants-browserify\\constants.json", "crypto": "D:\\react-native\\myapp\\node_modules\\crypto-browserify\\index.js", "dgram": null, "dns": null, "domain": "D:\\react-native\\myapp\\node_modules\\domain-browser\\source\\index.js", "events": "D:\\react-native\\myapp\\node_modules\\events\\events.js", "fs": null, "http": "D:\\react-native\\myapp\\node_modules\\stream-http\\index.js", "https": "D:\\react-native\\myapp\\node_modules\\https-browserify\\index.js", "module": null, "net": null, "os": "D:\\react-native\\myapp\\node_modules\\os-browserify\\browser.js", "path": "D:\\react-native\\myapp\\node_modules\\node-libs-browser\\node_modules\\path-browserify\\index.js", "process": "D:\\react-native\\myapp\\node_modules\\process\\browser.js", "punycode": "D:\\react-native\\myapp\\node_modules\\node-libs-browser\\node_modules\\punycode\\punycode.js", "querystring": "D:\\react-native\\myapp\\node_modules\\querystring-es3\\index.js", "readline": null, "repl": null, "stream": "D:\\react-native\\myapp\\node_modules\\stream-browserify\\index.js", "string_decoder": "D:\\react-native\\myapp\\node_modules\\string_decoder\\lib\\string_decoder.js", "sys": "D:\\react-native\\myapp\\node_modules\\util\\util.js", "timers": "D:\\react-native\\myapp\\node_modules\\timers-browserify\\main.js", "tls": null, "tty": "D:\\react-native\\myapp\\node_modules\\tty-browserify\\index.js", "url": "D:\\react-native\\myapp\\node_modules\\url\\url.js", "util": "D:\\react-native\\myapp\\node_modules\\util\\util.js", "vm": "D:\\react-native\\myapp\\node_modules\\vm-browserify\\index.js", "zlib": "D:\\react-native\\myapp\\node_modules\\browserify-zlib\\lib\\index.js"} was found.
  This is probably a typing mistake. Fixing it will remove this message.

@jacobmakarsky
Copy link

I'm getting the following error

Validation Warning:

  Unknown option "extraNodeModules" with value {"_stream_duplex": "D:\\react-native\\myapp\\node_modules\\readable-stream\\duplex.js", "_stream_passthrough": "D:\\react-native\\myapp\\node_modules\\readable-stream\\passthrough.js", "_stream_readable": "D:\\react-native\\myapp\\node_modules\\readable-stream\\readable.js", "_stream_transform": "D:\\react-native\\myapp\\node_modules\\readable-stream\\transform.js", "_stream_writable": "D:\\react-native\\myapp\\node_modules\\readable-stream\\writable.js", "assert": "D:\\react-native\\myapp\\node_modules\\assert\\assert.js", "buffer": "D:\\react-native\\myapp\\node_modules\\buffer\\index.js", "child_process": null, "cluster": null, "console": "D:\\react-native\\myapp\\node_modules\\console-browserify\\index.js", "constants": "D:\\react-native\\myapp\\node_modules\\constants-browserify\\constants.json", "crypto": "D:\\react-native\\myapp\\node_modules\\crypto-browserify\\index.js", "dgram": null, "dns": null, "domain": "D:\\react-native\\myapp\\node_modules\\domain-browser\\source\\index.js", "events": "D:\\react-native\\myapp\\node_modules\\events\\events.js", "fs": null, "http": "D:\\react-native\\myapp\\node_modules\\stream-http\\index.js", "https": "D:\\react-native\\myapp\\node_modules\\https-browserify\\index.js", "module": null, "net": null, "os": "D:\\react-native\\myapp\\node_modules\\os-browserify\\browser.js", "path": "D:\\react-native\\myapp\\node_modules\\node-libs-browser\\node_modules\\path-browserify\\index.js", "process": "D:\\react-native\\myapp\\node_modules\\process\\browser.js", "punycode": "D:\\react-native\\myapp\\node_modules\\node-libs-browser\\node_modules\\punycode\\punycode.js", "querystring": "D:\\react-native\\myapp\\node_modules\\querystring-es3\\index.js", "readline": null, "repl": null, "stream": "D:\\react-native\\myapp\\node_modules\\stream-browserify\\index.js", "string_decoder": "D:\\react-native\\myapp\\node_modules\\string_decoder\\lib\\string_decoder.js", "sys": "D:\\react-native\\myapp\\node_modules\\util\\util.js", "timers": "D:\\react-native\\myapp\\node_modules\\timers-browserify\\main.js", "tls": null, "tty": "D:\\react-native\\myapp\\node_modules\\tty-browserify\\index.js", "url": "D:\\react-native\\myapp\\node_modules\\url\\url.js", "util": "D:\\react-native\\myapp\\node_modules\\util\\util.js", "vm": "D:\\react-native\\myapp\\node_modules\\vm-browserify\\index.js", "zlib": "D:\\react-native\\myapp\\node_modules\\browserify-zlib\\lib\\index.js"} was found.
  This is probably a typing mistake. Fixing it will remove this message.

I'm getting the exact same thing

@cawfree
Copy link

cawfree commented Apr 25, 2020

I've started working on a dedicated native library as a workaround for these polyfill issues. There's a lot of work to be done, but I'll be focusing on feature parity for the coming months.

https://github.com/cawfree/web3-react-native

@HarshRajat
Copy link

This is what worked for me: Following @petercooke536 instructions and importing globals.js file for resolving btoa error.

@tigersze
Copy link

Anyone face the Error: not implemented problem when following the @ioitiki instructions?

@ravi0the0sun
Copy link

ravi0the0sun commented Aug 16, 2020

edited: this seems to work for me but i didnt do the

cd ios/
pod install
cd ..

and used android emulator
web3/web3.js#1022 (comment)

@cawfree
Copy link

cawfree commented Sep 7, 2020

You guys might be interested in this package; it's just a simple yarn add/npm install to start using Web3 in React Native.

@Hiti3
Copy link

Hiti3 commented Nov 23, 2020

Can anyone confirm any of the above reported solutions to still work in 2020 with the latest expo client?

@ravi0the0sun
Copy link

ravi0the0sun commented Nov 23, 2020

Hi @cawfree is your package able to generate an account in react native?

also update for ios
so when i try to build the ios app the app throws a build error
144 duplicate symbols for architecture x86_64
facebook/react-native#27840
I have tried the solutions mentioned in the thread but it didnt work for me anyone had this problem before?

@Hiti3
Copy link

Hiti3 commented Dec 9, 2020

@abcoathup Still have "Can't find variable: Buffer"

With
"expo": "^32.0.0",
"web3": "^1.0.0-beta.55"

When I put the global import in the same file as where I try to invoke the web3 library:

I get "The provided value 'ms-stream' is not a valid 'responseType'."

And "undefined is not an object (evaluating 'suerCtor.prototype')

Same here, any info on how to resolve this issue, please if you have any info on how to resolve it or either connect with web3 in any other RN way (expo or eject ?) I would surely appreciate it :)

@Hiti3
Copy link

Hiti3 commented Dec 9, 2020

Hi @osoese,
did you fix the warnings? I have the same problem.
Warning: The provided value 'ms-stream' is not a valid 'responseType'.
Warning: The provided value 'moz-chunked-arraybuffer' is not a valid 'responseType'.

same here, any info how you resolved it?

@Hiti3
Copy link

Hiti3 commented Dec 9, 2020

Got Expo (32) and Web3 working thanks to you all.

rn-cli.config.js format is:

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

module.exports = {
  resolver: {
    extraNodeModules: nodeLibs
  }
};

Created a boiler plate based on all of the above
https://github.com/abcoathup/expo-web3

The boiler plate seem not to work..

@ravi0the0sun
Copy link

hi @Hiti3 if you are creating your project using react-native cli then you may wanna follow this way
web3/web3.js#1022 (comment)
and also remember to remove the duplicate symbols for architecture x86_64 where you probably have to remove the CocoaAsync files from TcpSockets and react-native-udb pods as because of v0.62.0 auto linking
see the below link for more information.
tradle/rn-nodeify#94

@cawfree
Copy link

cawfree commented Dec 28, 2020

Hey all, I've made a dedicated script npx create-react-native-dapp to help bootstrap React Native applications with web3. It'll create an example app which will connect to ganache.

Hope this helps you.

https://github.com/cawfree/create-react-native-dapp

@devdomsos
Copy link

devdomsos commented Jul 20, 2021

I am trying to run the RN app without nodify with Web3. Does anybody have that working without nodify?

About secure randomNumber in RN :
In order to supply a secure randomNumber I used a different lib called ethers.js. You can follow a discussion on the subject here:
ethers-io/ethers.js#1070

Here is what will get you started:
https://docs.ethers.io/v5/cookbook/react-native/

Then you could create crypto global variable (I know not the best practice) and create a randomNumber:

export default function createCrypto(): Crypto {
  return {
    randomBytes(length: number = 32) {
      return Buffer.from(ethers.utils.randomBytes(length));
    };
  }
}    

I had to ejected from expo.

In the metro.config I specified also this:

resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg', 'tsx', 'ts'],
      extraNodeModules: {
        stream: require.resolve('stream-browserify'),
        crypto: require.resolve('crypto-browserify'),
      },
    },

It is not a complete solution, but might be helpful for some of you.

@devdomsos
Copy link

I am trying to run the RN app without nodify with Web3. Does anybody have that working without nodify?

About secure randomNumber in RN :
In order to supply a secure randomNumber I used a different lib called ethers.js. You can follow a discussion on the subject here:
ethers-io/ethers.js#1070

Here is what will get you started:
https://docs.ethers.io/v5/cookbook/react-native/

Then you could create crypto global variable (I know not the best practice) and create a randomNumber:

export default function createCrypto(): Crypto {
  return {
    randomBytes(length: number = 32) {
      return Buffer.from(ethers.utils.randomBytes(length));
    };
  }
}    

I had to ejected from expo.

In the metro.config I specified also this:

resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg', 'tsx', 'ts'],
      extraNodeModules: {
        stream: require.resolve('stream-browserify'),
        crypto: require.resolve('crypto-browserify'),
      },
    },

It is not a complete solution, but might be helpful for some of you.

@sakshambhatt
Copy link

Thank you!

@dhruvsbhatt
Copy link

node-libs-browser is deprecated now, any alternatives please.

@itsnyx
Copy link

itsnyx commented Feb 2, 2023

node-libs-browser is deprecated now, any alternatives please.

hey did u find any proper solution to use web3 in react native ?

@the-unknown
Copy link

node-libs-browser is deprecated now, any alternatives please.

hey did u find any proper solution to use web3 in react native ?

There is a fork, especially made for react native:

https://www.npmjs.com/package/node-libs-react-native

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment