Error importing blockstack.js in angular route guard

Hi all, I’m currently trying to create an authentication route guard in angular that will disallow the user from navigating to a page without being logged in to blockstack. I’ve installed blockstack and it’s in my package.json and I’m using the import statement from the docs, but when I run npm start the compile fails with this error:

ERROR in ./node_modules/blockstack/lib/encryption.js
Module not found: Error: Can’t resolve ‘crypto’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/blockstack/lib’
ERROR in ./node_modules/blockstack/lib/keys.js
Module not found: Error: Can’t resolve ‘crypto’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/blockstack/lib’
ERROR in ./node_modules/blockstack/lib/wallet.js
Module not found: Error: Can’t resolve ‘crypto’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/blockstack/lib’
ERROR in ./node_modules/blockstack/lib/storage/hub.js
Module not found: Error: Can’t resolve ‘crypto’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/blockstack/lib/storage’
ERROR in ./node_modules/jsontokens/lib/cryptoClients/secp256k1.js
Module not found: Error: Can’t resolve ‘crypto’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/jsontokens/lib/cryptoClients’
ERROR in ./node_modules/cipher-base/index.js
Module not found: Error: Can’t resolve ‘stream’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/cipher-base’
ERROR in ./node_modules/hash-base/index.js
Module not found: Error: Can’t resolve ‘stream’ in ‘/home/origin/Dev/blockstack/gitd/ng-web/node_modules/hash-base’

I’m guessing it’s something wrong with how I have my project setup but I’m really not sure. I tried adding the import to my app.module.ts and putting blockstack in the imports array but still no luck. Potentially related (but probably not the issue) is that my linter is telling me that it Could not find a declaration file for module 'blockstack'. '/home/origin/Dev/blockstack/gitd/ng-web/node_modules/blockstack/lib/index.js' implicitly has an 'any' type on my import statement. Any ideas?

1 Like

I happened to run into this very same issue today, except with an Ionic app. Interestingly, I’m not getting this issue in an Ionic app that doesn’t have the Angular Router installed, only with one that does have Angular Router installed.

The not-so-good news is that it would appear to be a feature, not a bug, of Angular

So far none of the workarounds people offered in this ^^ issue have worked for me.

This may be something that needs to be addressed in blockstack.js since the Angular team’s argument is that code that’s supposed to run in the client shouldn’t be dependent upon code that’s meant to run on the server.

2 Likes

Blockstack doesn’t support typescript per se, so there will not be any typings. I manually created them here via some fun workarounds with tsc. However this shouldn’t throw any errors; you’ll just have to use something akin to this:

import * as blockstack from 'blockstack.js'

which I assume you are already doing.

The obvious issue here is that it is requiring crypto and stream, which, according to the link @mizkirsten posted is “now standard behavior”. So the solution is to either use Angular 5 or create a branch of blockstack.js that uses web-compatible libraries instead of node libraries (like buffer etc).

tl;dr: use Angular 5 or start working on a fork of blockstack.js… sorry to bear the bad news.

3 Likes

Oof.

1 Like

Thanks for weighing in @MichaelFedora :slight_smile:

@originiam.id I’m exploring using something other than Angular Router because, at the moment, it seems like that’s where the conflict originates. I have an Ionic/Angular app using blockstack.js that does not use Angular Router (uses Ionic’s older push/pop lib) and doesn’t run into this issue when compiling. Assuming your app uses Angular Router?

Yup, I’m actually pretty new to angular but I just started an internship where that’s the framework that we’re using so I figured this would be a good chance to get more familiar with it. I ran into the issue trying to set up a basic authentication route guard to make sure the user was logged in

Quick follow up: I just discovered that my Ionic app without Angular Router is running Angular 5. So that explains it (not the absence of Angular Router). Just FYI. Both were bootstrapped on the same day from the latest CLI, so I didn’t anticipate getting different v’s of Angular depending upon which template I chose.

One last update for future Angular/Blockstack adventurers to use until a fork can be started. Here’s what I did to get rid of these errors after adding blockstack.js to my Ionic 4/Angular 7 app:

Change crypto to crypto-browserify in

  • node_modules/blockstack/lib/keys.js
  • node_modules/blockstack/lib/wallet.js
  • node_modules/blockstack/lib/wallet.js
  • node_modules/blockstack/lib/encryption.js
  • node_modules/blockstack/lib/storage/hub.js
  • node_modules/jsontokens/lib/cryptoClients/secp256k1.js

Change stream to stream-browserify in

  • node_modules/cipher-base/index.js
  • node_modules/hash-base/index.js
  • node_modules/browserify-sign/browser/index.js

Add the following three things to polyfills.ts

(window as any).global = window;

It seems far from ideal to be modifying the non-Blockstack files. I don’t know if there’s a way to deal with all of this via polyfills.ts instead of modifying those node lib files directly.

2 Likes

had the same issue couple days ago and then gave up

1 Like

Noticed you removed two of the lines you initially said to add to polyfill.ts, are they not actually necessary?

They seemed to be working at first, but, upon a hard restart of the app, they generated errors because each of them use require.

The result is that the app is loading now, but if I view a new page I created at /login, the page fails to load with this error

ReferenceError: process is not defined
    at Object../node_modules/process-nextick-args/index.js (index.js:3)
    at __webpack_require__ (bootstrap:83)
    at Object../node_modules/readable-stream/lib/_stream_readable.js (_stream_readable.js:26)
    at __webpack_require__ (bootstrap:83)
    at Object../node_modules/readable-stream/readable-browser.js (readable-browser.js:1)
    at __webpack_require__ (bootstrap:83)
    at Object../node_modules/stream-browserify/index.js (index.js:28)
    at __webpack_require__ (bootstrap:83)
    at Object../node_modules/hash-base/index.js (index.js:3)
    at __webpack_require__ (bootstrap:83)

According to Browserify:

Additionally, if you use any of these variables, they will be defined in the bundled output in a browser-appropriate way:

  • process
  • Buffer
  • global - top-level scope object (window)
  • __filename - file path of the currently executing file
  • __dirname - directory path of the currently executing file

So now I’m endeavoring to understand why I’m getting the undefined error for process :slight_smile: I’m reading through https://github.com/browserify/browserify-handbook.

Update! I’ve got it working :slight_smile: Again, the changes to the non-Blockstack.js files aren’t acceptable for the long-term, but maybe there’s a better solution (or maybe it’s just going to require doing a PR to those repo’s).

So, here’s the what works for me currently:
Change crypto to crypto-browserify in

  • node_modules/blockstack/lib/keys.js
  • node_modules/blockstack/lib/wallet.js
  • node_modules/blockstack/lib/wallet.js
  • node_modules/blockstack/lib/encryption.js
  • node_modules/blockstack/lib/storage/hub.js
  • node_modules/jsontokens/lib/cryptoClients/secp256k1.js

Change stream to stream-browserify in

  • node_modules/cipher-base/index.js
  • node_modules/hash-base/index.js
  • node_modules/browserify-sign/browser/index.js

In nodes_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js
change node: false; to node: { buffer: true }

Add this to polyfills.ts

(window as any).global = window;

(window as any).process = {
  env: { DEBUG: undefined },
};

There may be a way to at least package all these changes up into a single file that will do it all for you here https://gist.github.com/niespodd/1fa82da6f8c901d1c33d2fcbb762947d so that you don’t have to manually do it every time you update Angular. But even that is still hacky. If we’re all striving to make Blockstack as easy to integrate into Angular as it is into React, this ain’t the way :smiley: (But might at least point to the way.)

2 Likes

yes i totally agree, working with Blockstack and Angular is very frustrating!

I’ve been coding with it since last year before they had much support, so unfortunately I have been using a global version of Blockstack…which is currently making it very hard to upgrade my code to version 19 :slightly_frowning_face:

1 Like

@hank @yukan

Any idea on a roadmap to support Angular apps better? It’s kind of a show stopper for me right now being able to upgrade to blockstack.js v19 and Radiks

We don’t currently have plans to fully support Angular. As our resources are constrained, we’d need a better idea how many developers want to use it with Angular and how much work it would require to provide support. In the mean time, if community developers want to take this on feel free to send pull requests.

Thank you for this. I have been struggling as I developed and deployed, hours on fixing these code. I’m having problems with crypto after deployed and ran on browser. I’ll try changing the library.

@jessicaanhdao

Angular actually does a very poor job in the default web pack config. They actually remove the crypto library although its web standard now.

To solve this you need to have a custom webpack config that uses a browserified version of node.js’s crypto library. This article walks thru how to do this https://codeburst.io/customizing-angular-cli-6-build-an-alternative-to-ng-eject-a48304cd3b21

If you get stuck my app Sheety App has blockstack working properly with angular configured here: https://github.com/ntheile/sheety-app/blob/master/ClientApp/extra-webpack.config.js

Hi All,

We have created Angular+Blockstack project which is working perfectly. It has even node modules. Just download from git and start build your own idea. (you can even upgrade angular to latest version)

Thanks.

1 Like