Problem
If you're a JavaScript/Web developer interested in working with Bitcoin then you've undoubtedly come across, bitcore, one of the widely used libraries. It is an open-source software published and maintained by Bitpay and used in many popular tutorials such as BCH Wallet and Pluralsight.
However, the library was designed for web apps and will break your React Native mobile app if used 'out-of-the-box'.
In our basic code example below, we try to initialize a new private key on initial app render.
App.js
export default function App() {
const [privateKey, setPrivateKey] = useState();
useEffect(() => {
setPrivateKey(new bitcore.PrivateKey("testnet"));
}, []);
return (
<View style={styles.container}>
<Text>{`Testnet private key: ${privateKey}`}</Text>
<StatusBar style="auto" />
</View>
);
}
The bitcore.privateKey method will throw the following error message: Unable to resolve module crypto... which results in the 'red screen of death'.
Alternatively, you may also see Unable to resolve module buffer... message.
Reason
The gist of it is that React Native does not use the Node runtime environment and thus does not have access to specific libraries such as 'crypto', 'assert', 'url', etc. For the vast majority of use cases, this is not a problem, but working with cryptocurrency happens to be an exception.
Solution
There are several workarounds that exist and unfortunately all of them lack elegance.
In this example, we use rn-nodeify to enable core node modules in our React Native app.
Step 1: eject expo
If your app is using the expo managed workflow, you'll need to eject.
This is an irreversible process.
By ejecting, you will no longer be able to use some of the expo cli commands such as start, build, etc. Also, you'll need to use xcode and android studio directly in order to run the app in the development environment.
On the other hand, all expo specific libraries (i.e. @expo/vector-icons, expo-splash-screen, etc) will work with little to no tweaks.
To eject:
From your project directory, run
expo eject
. This will download the required dependencies and build native projects under the ios and android directories.
Source: expo docs
After running the above command, your project directory should now contain android & ios directories and index.js & metro.config.js files.
Step 1.5: run app in simulator via xcode
Update libraries:
- Delete package-lock file if you have one
- Run
yarn
- Change to ios directory
cd ios
- Delete the podfile.lock if you have one
- Run
pod install
Open xcode and select Open a project or file option. Navigate to the ios directory and select open.
Click the play button to build and run your app on ios simulator.
It is very common at this stage to run into issues usually dealing with updating packages.
Step 2: install package rn-nodeify
In the root directory of your app run the following command:
yarn add rn-nodeify -D
This command creates a boilerplate file, shim.js, in the root directory. Import this file at the very top of your index.js.
import "./shim";
Step 3: modify package.json file
Update the package.json file to include a postinstall script.
"scripts": {
"start": "react-native start",
~~~
"postinstall": "node_modules/.bin/rn-nodeify --install crypto,assert,url,stream,events --hack"
},
Through a bit of trial and error I discovered that the above packages in the postinstall script are necessary dependencies for the bitcore library.
Step 4: restart your app
Close down your metro terminal, simulator and then restart your app by pressing the play button in Xcode.
You should see the following screen:
Congratulations, you're now on your way to creating the next crypto app.
It is possible to run into additional errors at this stage. For example, on my second attempt at this process, I was getting 'Process could not be found in this project' error. I simply had to 'yarn add process' to get it working again.
As an aside, this method hasn't been battle tested and could potentially have security issues.
Top comments (0)