Skip to content

Instantly share code, notes, and snippets.

@coreyphillips
Last active April 25, 2024 22:07
Show Gist options
  • Save coreyphillips/4d45160fed016417a5f583f179c2cbdb to your computer and use it in GitHub Desktop.
Save coreyphillips/4d45160fed016417a5f583f179c2cbdb to your computer and use it in GitHub Desktop.
How To Add bitcoinjs-lib To A React Native v0.60+ Project

How To Add bitcoinjs-lib To A React Native v0.60+ Project

Add/Link the following dependencies:

  • yarn add bitcoinjs-lib ecpair @bitcoinerlab/secp256k1 react-native-randombytes buffer readable-stream
  • yarn add --dev rn-nodeify
  • cd ios && pod install && cd ..
  • Add the following postinstall to your script in package.json: "postinstall": "rn-nodeify --install buffer,stream,assert,events,crypto,vm,process --hack"

Install any remaining dependencies and run postinstall.

NOTE: (If you receive an error about "shim.js" not existing just run yarn install again):

  • yarn install

  • Uncomment require('crypto') at the bottom of "shim.js". Or add require('crypto') to the bottom of "shim.js" if it doesn't exist.

  • And finally, yarn install && cd ios && pod install && cd .. one more time.

To test if everything is working as expected place the following in render:

import './shim';
import ECPairFactory from 'ecpair';
import ecc from '@bitcoinerlab/secp256k1';
const bitcoin = require('bitcoinjs-lib');
const ECPair = ECPairFactory(ecc);
const keyPair = ECPair.makeRandom();
const {address} = bitcoin.payments.p2pkh({pubkey: keyPair.publicKey});
console.log(address);

An unedited video walkthrough of this guide can be found here:

@coreyphillips
Copy link
Author

@dnovacik, a bit late here, but that is correct. You would have to eject from Expo in order for this to work.

@fabu21
Copy link

fabu21 commented Jun 19, 2022

Hi guys.
I tried everything with this gist but I can't get it running. The error I get now is the following:

TypeError: undefined is not an object (evaluating '_bitcoinjsLib.default.ECPair')

I tried with newer packages, maybe that is the problem:

"dependencies": {
"assert": "^1.5.0",
"bitcoinjs-lib": "^6.0.1",
"buffer": "^6.0.3",
"ecpair": "^2.0.1",
"events": "^1.1.1",
"process": "^0.11.10",
"react": "17.0.2",
"react-native": "0.68.2",
"react-native-crypto": "^2.2.0",
"react-native-randombytes": "^3.6.1",
"readable-stream": "^4.0.0",
"stream-browserify": "^1.0.0",
"vm-browserify": "^0.0.4"
},

Any ideas? Thanks!

@coreyphillips
Copy link
Author

Using the newer version of bitcoinjs-lib requires the use of the ecpair and tiny-secp256k1 library to get hold of the keypair like so:

import "./shim";
import ECPairFactory from 'ecpair';
import * as ecc from 'tiny-secp256k1';
const ECPair = ECPairFactory(ecc);
const bitcoin = require("bitcoinjs-lib");
const keyPair = ECPair.makeRandom();
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey });
console.log(address);

Bitcoinjs-lib also updated their docs to reflect these changes here. Hope this helps!

@fabu21
Copy link

fabu21 commented Jun 22, 2022

Thanks for your reply. I thought I could get this running without tiny-secp256k1 which adds more problems. This is what I did now:

yarn add ecpair tiny-secp256k1

which resulted in the error:
error: Error: While trying to resolve module tiny-secp256k1 from file /home/xxx/Dev/tests/MyApp/App.js, the package /home/xxx/Dev/tests/MyApp/node_modules/tiny-secp256k1/package.json was successfully found. However, this package itself specifies a main module field that could not be resolved (/home/xxx/Dev/tests/MyApp/node_modules/tiny-secp256k1/lib/cjs/index.cjs. Indeed, none of these files exist:

This seems to be a Issue in metro, so I added the following in metro.config.js:

const { getDefaultConfig } = require("metro-config"); const { resolver: defaultResolver } = getDefaultConfig.getDefaultValues();

and

resolver: { ...defaultResolver, sourceExts: [ ...defaultResolver.sourceExts, "cjs", ], },

inside module.exports = .

This leads to the following error:

Unable to resolve module fs from /home/xxx/Dev/tests/MyApp/node_modules/tiny-secp256k1/lib/cjs/wasm_loader.cjs: fs could not be found within the project or in these directories

So I added fs and path in the postinstall script in package.json:

"postinstall": "rn-nodeify --install buffer,stream,assert,events,crypto,vm,process,fs,path --hack"

now I'm stuck with this error when I run "npm run android".

TypeError: (0, _$$_REQUIRE(_dependencyMap[0], "fs").readFileSync) is not a function. (In '(0, _$$_REQUIRE(_dependencyMap[0], "fs").readFileSync)((0, _$$_REQUIRE(_dependencyMap[1], "./wasm_path_cjs.cjs").path)("secp256k1.wasm"))', '(0, _$$_REQUIRE(_dependencyMap[0], "fs").readFileSync)' is undefined)

Any idea how I can fix that?
Thanks!

@divyangkhatri
Copy link

Hello @coreyphillips ,
I am also readFileAysnc issue.
Please check the below error.
TypeError: (0, fs_1.readFileSync) is not a function. (In '(0, fs_1.readFileSync)((0, wasm_path_cjs_js_1.path)("secp256k1.wasm"))', '(0, fs_1.readFileSync)' is undefined)

For fs usning fs:react-native-level-fs.

as per react-native-level-fs is not support readasyncfile.

Can you please tell me about another way of generating the bitcoin wallet.

@heroims
Copy link

heroims commented Sep 9, 2022

you can use npm install tiny-secp256k1@1.1.1 . old version is ok

Hello @coreyphillips , I am also readFileAysnc issue. Please check the below error. TypeError: (0, fs_1.readFileSync) is not a function. (In '(0, fs_1.readFileSync)((0, wasm_path_cjs_js_1.path)("secp256k1.wasm"))', '(0, fs_1.readFileSync)' is undefined)

For fs usning fs:react-native-level-fs.

as per react-native-level-fs is not support readasyncfile.

Can you please tell me about another way of generating the bitcoin wallet.

@losh11
Copy link

losh11 commented Jan 19, 2023

Getting TypeError: ecc.privateNegate is not a function. Using tiny-secp256k1@1.1.6 in order to avoid wasm/cjs.
Crypto shimming is enabled.

@sh4dowb
Copy link

sh4dowb commented Jan 19, 2023

Getting TypeError: ecc.privateNegate is not a function. Using tiny-secp256k1@1.1.6 in order to avoid wasm/cjs. Crypto shimming is enabled.

what I finally did was,
yarn add bip32@2.0.6

then

import "./../shim";
let bip39 = require('bip39')
let bip32 = require('bip32')
let bitcoin = require('bitcoinjs-lib')

    let seed = bip39.mnemonicToSeedSync("mnemonic goes here")
    let hdNode = bip32.fromSeed(seed)

    let childNode = hdNode.deriveHardened(0)
    let external = childNode.derive(1)
    console.log(bitcoin.payments.p2pkh({pubkey: external.publicKey}))

I've not tried generating a mnemonic though

@losh11
Copy link

losh11 commented Jan 20, 2023

@sh4dowb I'm currently working on updating this guide. A few years ago a lot of these shimming tools worked fine, but with modern RN and when used with more complex setups, it doesn't work. That and also half of the tools are no longer being maintainer, including rn-nodeify, react-native-crypto, react-native-randombytes etc.

Instead there are much better polyfills available, which are less hacky and more stable.

@Ariflo
Copy link

Ariflo commented Feb 14, 2023

Uncomment require('crypto') at the bottom of "shim.js". Or add require('crypto') to the bottom of "shim.js" if it doesn't exist.

If you happen to come upon this and like me are working with an Expo based application; simply ignore this step, do not comment out this line and everything should work just as well for you :-)

@tiero
Copy link

tiero commented Mar 7, 2023

@losh11 Do you managed to work on the guide? I am same situation and can't make of use of rn-nodefy due Expo (which I can't eject)

@losh11
Copy link

losh11 commented Mar 7, 2023 via email

@tiero
Copy link

tiero commented Mar 7, 2023

@losh11 I see. Can I take a look at your solution? Did you use rn-nodefy still?

@losh11
Copy link

losh11 commented Mar 7, 2023 via email

@coreyphillips
Copy link
Author

coreyphillips commented May 17, 2023

@losh11, any updates on your end regarding this?

I've become aware of a few drop-in alternatives that popped up (https://github.com/bitcoinerlab/secp256k1) that may be helpful.

@losh11
Copy link

losh11 commented May 21, 2023

@coreyphillips trying to figure out from commit history... inject buffer/crypto/stream & change noblesecpk1 lib

Requires adding these deps

  • @bitcoinerlab/secp256k1
  • @craftzdog/react-native-buffer
  • react-native-quick-base64
  • react-native-quick-crypto
  • stream-browserify
  • babel-plugin-module-resolver (dev dep)

Looks like I added the following to babel.config.js:

[
      'module-resolver',
      {
        alias: {
          crypto: 'react-native-quick-crypto',
          stream: 'stream-browserify',
          buffer: '@craftzdog/react-native-buffer',
        },
      },
    ],

Replace all import {Buffer} from 'buffer'; to import {Buffer} from '@craftzdog/react-native-buffer';
Replace all import bjs from 'bitcoinjs-lib'; to import ecc from '@bitcoinerlab/secp256k1'; and import {...} from 'bitcoinjs-lib';

Add to top of index.js

import {Buffer} from '@craftzdog/react-native-buffer';
window.Buffer = Buffer;

That's it! Pain in the butt. Took me 2 days to figure out.

@coreyphillips
Copy link
Author

Nice, thanks @losh11! I'll attempt to give it a go when some time becomes available and update or create a new gist with some working code and examples.

@evzpav
Copy link

evzpav commented Jun 8, 2023

@losh11
Copy link

losh11 commented Jun 8, 2023

happy to see this @evzpav!

@evzpav
Copy link

evzpav commented Jun 8, 2023

Did anybody had any success making bitcoinjs-lib working with Expo on React Native?

@coreyphillips
Copy link
Author

@evzpav Nice! Awesome to see we have a viable boilerplate.

As another option, I'm trying to go the JSI route by wrapping libsecp256k1 into a usable RN library that we can import. Not having much luck linking it though.

@zireal23
Copy link

I am trying the steps with react native on expo but getting the error "cannot resolve invariant". Any fixes? Has anyone managed to get it working with expo?

@losh11
Copy link

losh11 commented Jun 23, 2023

@zireal23 do you have a repo we could try?

@zireal23
Copy link

@losh11 thanks for the reply, but I got it to work by polyfilling buffer and patching the library to always populate the global.buffer.

@junderw
Copy link

junderw commented Jul 22, 2023

https://www.npmjs.com/package/@bitcoin-js/tiny-secp256k1-asmjs

Released asmjs version of tiny-secp256k1.

Also, @bitcoinerlab/secp256k1 also implements the same interface and is slightly faster (but it uses native JS BigInt, so if your build environment can't handle that, you can't use it)


Also, I find it strange that so many people still have trouble with RN? BlueWallet has been using bitcoinjs-lib with RN for years and they've never complained once...

Granted, I am not well versed in RN and all of its strange ways.

@coreyphillips
Copy link
Author

Thanks again @junderw!

I've updated the guide to use @bitcoin-js/tiny-secp256k1-asmjs.

Regarding RN/bitcoinjs-lib trouble, the first-time setup for a project can be tricky and some devs tend to default to Expo which can bring some additional complications. Once a project is setup successfully on a particular version it's not an issue to maintain. However, as seen with tiny-secp256k1, any change/upgrade to a crypto library can be difficult in RN.

@parthindia47
Copy link

parthindia47 commented Mar 5, 2024

Hi,
I followed all this steps but I am getting following error, any idea ?

``Error: While trying to resolve module @bitcoin-js/tiny-secp256k1-asmjs from file `C:\Users\Parth\Documents\Development\crypto-wallet-app\LCRN14-crypto-wallet-app-master\utils\SimBSC.js`, the package `C:\Users\Parth\Documents\Development\crypto-wallet-app\LCRN14-crypto-wallet-app-master\node_modules@bitcoin-js\tiny-secp256k1-asmjs\package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`C:\Users\Parth\Documents\Development\crypto-wallet-app\LCRN14-crypto-wallet-app-master\node_modules@bitcoin-js\tiny-secp256k1-asmjs\lib\cjs\index.cjs`. Indeed, none of these files exist:`
`

@coreyphillips
Copy link
Author

@parthindia47, do you have any luck swapping out @bitcoin-js/tiny-secp256k1-asmjs for @bitcoinerlab/secp256k1?

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