Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.

@code-brewer
Copy link

code-brewer commented Jan 8, 2019

Hi, dougbacelar.

On step 9, you using :
const Web3 = require('web3');
Why not:
import {Web3} from 'web3'

Does it because web3.js don't support ES module style usage ?

@boxfox619
Copy link

boxfox619 commented Mar 22, 2019

I haved a error like 'can not find variable Buffer, can not find http etc.'
So, i change rn-cli.config.

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

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

and then i solve this problem.

Enviroment :

@ioitiki
Copy link

ioitiki commented Mar 28, 2019

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

@abcoathup
Copy link

abcoathup commented Mar 29, 2019

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

@nickjuntilla
Copy link

nickjuntilla commented May 28, 2019

@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')

@JitendraLakhmani1824
Copy link

JitendraLakhmani1824 commented May 30, 2019

I am facing same issue, "Undefined is not an object (evaluating 'superCtor.prototype')".Any fix?

@osoese
Copy link

osoese commented Jun 21, 2019

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

Thank you for the boiler plate! I am not 100% sure what you did that I did not do yet but it is the first thing that worked on expo ^v30

I see a couple strange warnings in the console but the blocks are there too

Warning: The provided value 'ms-stream' is not a valid 'responseType'.
Warning: The provided value 'moz-chunked-arraybuffer' is not a valid 'responseType'.

@minuitagency
Copy link

minuitagency commented Jul 2, 2019

Hi,

I have an issue, it works great on simulator and I can generate keys but it doesn’t work on device, does anyone have an idea ?

Thanks,
Théo

@petercooke536
Copy link

petercooke536 commented Aug 12, 2019

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

Hi @ioitiki I tried following your steps to create a react native project with Web3 but I cant seem to get it working. I am getting a error that it cant find the varibale btoa. Is there anyway you could post the project that you got it working for?

@fcubel
Copy link

fcubel commented Sep 6, 2019

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'.

@ZeeshanAhmadKhalil
Copy link

ZeeshanAhmadKhalil commented Dec 1, 2019

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

@ZeeshanAhmadKhalil
Copy link

ZeeshanAhmadKhalil commented Dec 1, 2019

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

rohankeskar19 commented Jan 6, 2020

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

jacobmakarsky commented Feb 6, 2020

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

HarshRajat commented May 1, 2020

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

@tigersze
Copy link

tigersze commented May 11, 2020

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

ravi0the0sun commented Dec 14, 2020

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

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.

@sakshambhatt
Copy link

sakshambhatt commented Aug 23, 2021

Thank you!

@dhruvsbhatt
Copy link

dhruvsbhatt commented Jun 20, 2022

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

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