js-stellar-sdk icon indicating copy to clipboard operation
js-stellar-sdk copied to clipboard

Document how to get working on React Native

Open morleyzhi opened this issue 6 years ago • 15 comments

Copy Nando's instructions below to a place and in a format where devs can set this up on RN themselves.

morleyzhi avatar May 20 '19 18:05 morleyzhi

@fnando Did you write up a guide for the stuff you had to do to get this working? The real mitigation seems like enough work that maybe we should just tell people to do what you did, if the list of steps isn't onerous.

morleyzhi avatar May 20 '19 21:05 morleyzhi

@morleyzhi No, but I can write down the steps. There aren't many, but is kinda tricky to get everything working. I'll add it to my tasks of the week.

fnando avatar May 21 '19 17:05 fnando

@morleyzhi We were dealing with this eventsource logic issue when working with the @pigzbe/react-native-stellar-sdk polyfill and upgrading to v.0.15.0. See #2. The @pigzbe/react-native-stellar-sdk implementation uses react-native-randombytes.

Still, I ended up having to fork js-stellar-sdk to hack the logic for detecting whether we were on RN in call_builder.js#L13.

The combo of @mikeyrf/js-stellar-sdk & @mikeyrf/react-native-stellar-sdk repos has been working in our RN app, although my js-stellar-sdk fork is only on v. 0.15.0.

mikeyrf avatar May 21 '19 18:05 mikeyrf

@mikeyrf I was able to make it work without using forks by using https://github.com/tradle/rn-nodeify. I'm curious if you tried that before going the fork route.

fnando avatar May 21 '19 18:05 fnando

Cool, that's good to know! If there's a real performance gain to making keyPair run async, it sounds like we need to do a hybrid approach, where we fix as many of these bugs as we can (probably through platform detection) AND have a guide to shim the stuff we can't fix.

morleyzhi avatar May 21 '19 18:05 morleyzhi

@fnando I did but I wasn't able to get things running. It might have been because I'm using an ejected version of expo, not sure tho.

@morleyzhi From a UX perspective, the keyPair generation w async isn't a huge problem, since most users expect the initialization of their accounts to take some time within a signup flow. Since Stellar is account based, I really only call that function once during onboarding (then thats it).

I tend to prefer the @pigzbe/react-native-stellar-sdk polyfill approach, where js-stellar-sdk doesn't have anything RN in it.

Ideally, stellar would have an official rn-stellar-sdk polyfill repo that users can simply yarn add, then react-native link react-native-randombytes and you're good. The @pigzbe/react-native-stellar-sdk README.md details this well.

mikeyrf avatar May 21 '19 19:05 mikeyrf

Here are the steps to make stellar-sdk work with react-native:

  1. Add the following postinstall script:
yarn rn-nodeify --install url,events,https,http,util,stream,crypto,vm,buffer --hack --yarn
  1. yarn add -D rn-nodeify
  2. Uncomment require('crypto') on shim.js
  3. react-native link react-native-randombytes
  4. Create file rn-cli.config.js
module.exports = {
  resolver: {
    extraNodeModules: require("node-libs-react-native"),
  },
};
  1. Add import "./shim"; to the top of index.js
  2. yarn add stellar-sdk

I have a sample app configured with these exact steps at https://github.com/fnando/rn-stellar-sdk-sample

fnando avatar May 22 '19 00:05 fnando

Wonder if it's even possible to pass a random number generator and default to Node's crypto module or the Web Crypto API on browsers.

This seems to not blow up (emphasis on seems) on Expo if you:

  1. Grab a copy of the SDK from the CDN and save to disk
  2. Edit the SDK like so:
// import `expo-random` a write `global.crypto`
import * as Random from 'expo-random';

global.crypto = {
  randombytes: Random.getRandomBytes,
  randomBytes: Random.getRandomBytes
}

Then scroll down until you find:

} else if (true) {
  // Node.js.
  // crypto = __webpack_require__(193); <-- Comment out this line
  if (crypto && crypto.randomBytes) {
    nacl.setPRNG(function(x, n) {
      var i, v = crypto.randomBytes(n);
      for (i = 0; i < n; i++) x[i] = v[i];
      cleanup(v);
    });
  }
}

Finally, you need to export the StellarSdk

// at the EOF
export default StellarSdk;

With these changes I can generate keypairs without the need to eject my Expo project.

silvestreh avatar Oct 25 '21 22:10 silvestreh

Here's how you can do it on Expo without the need to edit the SDK as in my previous comment, nor having to eject to add react-native-randombytes. It's almost the same approach as @fnando's, but uses expo-random instead (also, I'm using npm instead of yarn)

  1. npm i -D rn-nodeify
  2. Add a new NPM postinstall script: rn-nodeify --install process,url,events,https,http,util,stream,vm,buffer --hack
  3. Import the generated ./shim.js file at the top of your app's entry — by default, it's located in ./App
  4. npm i stellar-sdk

At this point, the stellar SDK will work, except that StellarSdk.Keypair.random() will throw an error. So to work around this you can create your own method to generate a random keypair like this:

import * as Random from 'expo-random';
import StellarSdk from 'stellar-sdk';

const generateRandomKeypair = () => {
  const randomBytes = Random.getRandomBytes(32);

  return StellarSdk.Keypair.fromRawEd25519Seed(Buffer.from(randomBytes));
};

silvestreh avatar Oct 29 '21 20:10 silvestreh

I just made a thing that could make Expo users' life a lil' bit easier.

https://github.com/silvestreh/expo-stellar-sdk

It basically is just a wrapper for the Stellar SDK that overrides the Keypair.random method like on my previous comment and shims some node modules so that the SDK works in Expo managed workflows.

silvestreh avatar Nov 30 '21 17:11 silvestreh