How to use HiveJs (or other modules referencing core Node.js modules) on React Native

in HiveDevs4 years ago (edited)

image.png

As some of you may know, I am developing a Hive Keychain App for mobile using React Native (RN). @revo asked me how I managed to use Hive related modules on RN.

Although RN uses Javascript, some npm modules won't work directly because they use Node.js core modules such as assert and crypto.

It's a bit tedious to make it work, but I truly hope to see more mobile Application in our ecosystem, so I'm writing this tutorial hoping it will be of some help.

Babel to the rescue!

We will use Babel and rewrite-require preset to rewrite some of these modules to use React Native or browserified packages instead.

Let's see step by step how this is working out on a new project.

Step 1 : Create a new project

I will assume you already have your environment setup and that we are making a classic React Native project (no expo) :

npx react-native init [ProjectName]

Step 2 : Add Hivejs

Run

npm i @hiveio/hive-js --save

Let's try it out, on App.js, add the following lines after the imports :

import hivejs from '@hiveio/hive-js'

(async function () {
  console.log(await hivejs.api.getAccountsAsync(['stoodkev']));
})();

Try to run the App and bim! Error!

error: Error: Unable to resolve module `assert` from `node_modules/@hiveio/hive-js/lib/auth/memo.js`: assert could not be found within the project.

That's because React Native has no idea what assert or crypto modules are, since they are Node.js core modules.

Step 3 : Babel Config

Find your babel file, babel.config.js.
Note that the name might be slightly different such as .babelrc or .babel-cli.

Add the following lines to the existing config :

sourceMaps: true,
plugins: [
        [
            'rewrite-require',
            {
                aliases: {
                    crypto: 'react-native-crypto',
                    constants: 'constants-browserify',
                    dns: 'node-libs-browser/mock/dns',
                    domain: 'domain-browser',
                    fs: 'node-libs-browser/mock/empty',
                    http: 'stream-http',
                    https: 'https-browserify',
                    net: 'node-libs-browser/mock/net',
                    os: 'os-browserify/browser',
                    path: 'path-browserify',
                    pbkdf2: 'react-native-pbkdf2-shim',
                    querystring: 'querystring-es3',
                    stream: 'stream-browserify',
                    _stream_duplex: 'readable-stream/duplex',
                    _stream_passthrough: 'readable-stream/passthrough',
                    _stream_readable: 'readable-stream/readable',
                    _stream_transform: 'readable-stream/transform',
                    _stream_writable: 'readable-stream/writable',
                    sys: 'util',
                    timers: 'timers-browserify',
                    tls: 'node-libs-browser/mock/tls',
                    tty: 'tty-browserify',
                    vm: 'vm-browserify',
                    zlib: 'browserify-zlib',
                },
                throwForNonStringLiteral: true,
            },
        ],
    ],

Install the following dependencies :

npm i --save babel-plugin-rewrite-require events assert react-native-crypto stream react-native-randombytes vm-browserify process

Also add manually this dependency in package.json then npm install :

"react-native-pbkdf2-shim": "git+https://[email protected]/wswoodruff/react-native-pbkdf2-shim.git"

Step 4 : Add globals

If you try to run the code now you should see this error :

ExceptionsManager.js:76 Error: Buffer not supported in this environment. Use Node.js or Browserify for browser support.

Create a global.js file on the root of the project :

// Inject node globals into React Native global scope.
global.Buffer = require('buffer').Buffer;
global.process = require('process');
global.process.env.NODE_ENV = __DEV__ ? 'development' : 'production';

// Needed so that 'stream-http' chooses the right default protocol.
global.location = {
  protocol: 'file:',
};

// Don't do this in production. You're going to want to patch in
// https://github.com/mvayngrib/react-native-randombytes or similar.
global.crypto = {
  getRandomValues(byteArray) {
    for (let i = 0; i < byteArray.length; i++) {
      byteArray[i] = Math.floor(256 * Math.random());
    }
  },
};

And import it from App.js :

import './global.js'

Step 5: Voila!

HiveJs should now be working and you should see my account info in your debugger.

If you are still getting errors, try cleaning the modules :

rm -rf node_modules && npm install && npx jetify

I uploaded my code to Github for reference, I hope this will help future Hive mobile devs ;)

If you have questions or encounter some issues, don't hesitate to ask me questions in the comment section.

Hive on!


@stoodkev
Hive Keychain PO
If you find my work valuable, please consider voting for my Witness

Sort:  

Nice! 👍
We use dhive library in Ecency/Esteem mobile app, could be useful for RN developers to check it out as well: https://github.com/ecency/esteem-mobile

Yea, that's what I've used on hive keychain mobile actually.

I'm hoping to continue using hive-js, as I've been using it for years and know how it works. Unfortunately with DHive there's not very much documentation. If I end up using it I'll be pestering you and @stoodkev for tips.. 😅

Sure, here is documentation for dhive and how to use it: https://openhive-network.github.io/dhive/

Ok, cheers for that. That's a bit more than is on Github. I'm just in the process now of trying to get hive-js going via stoodkev's example above.

It's a bit tedious to make it work, but I truly hope to see more mobile Application in our ecosystem

Yea me too. But, we don't have any native Java libraries for Hive which is why mobile-app development has been slow.

Also, javascript is client-side intensive which makes mobile apps even laggier. Using NATIVE JAVA is the best. I managed to port all of the critical Hive operations to Java a couple years back but I haven't open sourced it. I probably will in the future though when I actually have time to work and clean my code up.

Would be interested in this library...

Thanks for this @stoodkev!

 4 years ago  

Please use @hiveio/hive-js, the @hivechain/hive-js is deprecated.

Thanks, updating now.
That won't change anything to the process though.

Unfortunately using @hiveio/hive-js seems to break it. It works fine with @hivechain/hivejs, but when I swap in the newer package it gives the following error
Untitled.png
Untitled2.png

 4 years ago  

We used requrie.resolve in the new release of hive-js for hf24 compatibility. I think you can fix this error too. @stoodkev

Yea I ll check how to solve this on RN when I have some time and will update the repo.

Congratulations @stoodkev! You received a personal badge!

Happy Hive Birthday! You are on the Hive blockchain for 3 years!

You can view your badges on your board And compare to others on the Ranking

Do not miss the last post from @hivebuzz:

Hive Power Up Day - Let's grow together!
The HiveBuzz Shop - New Items and Designs