hirosystems / stacks.js

JavaScript libraries for identity, auth, storage and transactions on the Stacks blockchain.
https://stacks.js.org
MIT License
947 stars 308 forks source link

How to use it with Angular #751

Closed negue closed 3 years ago

negue commented 4 years ago

Is there any example to get it running with Angular?

I added import * as blockstack from 'blockstack'; but all I get is:


ERROR in node_modules/blockstack/lib/encryption/ec.d.ts:2:21 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.

2 import * as BN from 'bn.js';
                      ~~~~~~~
node_modules/blockstack/lib/network.d.ts:2:21 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.

2 import * as BN from 'bn.js';
                      ~~~~~~~
node_modules/blockstack/lib/operations/skeletons.d.ts:1:21 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.

1 import * as BN from 'bn.js';
                      ~~~~~~~
node_modules/blockstack/lib/operations/txbuild.d.ts:1:21 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.

1 import * as BN from 'bn.js';

Option allowSyntheticDefaultImports is enabled

Any ideas / workarounds ?

I hoped that Angular and blockstack both using typescript it shouldn't be a problem to use blackstack :/

zone117x commented 4 years ago

This is actually an issue with the @types/bn.js package, or at least how it is being imported.

I created this PR which should fix the issue if approved https://github.com/DefinitelyTyped/DefinitelyTyped/pull/41255

For now, you can work around this by specifying skipLibCheck: true in your tsconfig.json

negue commented 4 years ago

Oh I see.

I added skipLibCheck: true this way it compiles fine.

But at runtime I got this: Uncaught ReferenceError: global is not defined

Using this solution: https://stackoverflow.com/a/59249136/1298154

(window as any).global = window;
global.Buffer = global.Buffer || require('buffer').Buffer;
(window as any).process = {
  version: ''
};

Now it works at runtime too. 🎉

Maybe this should be somewhere in the docs, I guess many that tried with angular, got this issue and stopped after it ^^

In case anyone wants to have a "working" runtime demo: https://github.com/negue/blockstack-test

negue commented 4 years ago

Building ng build the angular app I also get this

ERROR in ./node_modules/blockstack/lib/keys.js
Module not found: Error: Can't resolve 'crypto'

I hope #737 will help with that

zone117x commented 4 years ago

You'll have to elaborate more on what you mean by "android app". Current blockstack.js depends on the node.js 'crypto' module, or for a bundler like webpack or browserify to polyfill it. That WebCrypto PR will remove the node.js 'crypto' module requirement for modern web browsers, however, the Android js runtime you are using may not provide the WebCrypto APIs.

negue commented 4 years ago

Oof sorry, I really did write android .. , brain auto correction :D sorry about that, I meant angular! (Edited the message above too)

I'll try a node crypto polyfill later today and post again with the results

zone117x commented 4 years ago

I took a cursory look at the ng build command (here: https://angular.io/cli/build) and it says webpack w/ default settings is used behind the scenes. Default webpack settings should have provided the various polyfills mentioned in this issue.

Could you post your build settings/config?

negue commented 4 years ago

Its finally compiling and working.

for the crypto error, I had to add this to my package.json:

"browser": {
  "crypto": false
}
zone117x commented 4 years ago

The bn.js skipLibCheck bug was fixed in the upstream dependencies. Once https://github.com/blockstack/blockstack.js/pull/753 is merged, the flag should no longer be necessary.

@negue

for the crypto error, I had to add this to my package.json: ...

That crypto package.json fix will no longer be necessary once https://github.com/blockstack/blockstack.js/pull/737 is merged.

johannesjo commented 4 years ago

crypto is indeed not needed anymore, but now stream is.

johannesjo commented 4 years ago

Unfortunately using "stream": false leads to a new error for cipher-base:

TypeError: Cannot read property 'call' of undefined
    at Hash.CipherBase (index.js:7)
    at new Hash (browser.js:9)
    at createHash (browser.js:29)
    at sha256x2 (index.js:8)
    at Object.encode (base.js:9)
    at Object.toBase58Check (address.js:35)
    at Object.publicKeyToAddress (keys.js:35)
    at Object.makeAuthRequest (authMessages.js:88)
    at UserSession.makeAuthRequest (userSession.js:142)
    at UserSession.redirectToSignIn (userSession.js:89)

If I don't I get this error during compilation:

ERROR in ./node_modules/cipher-base/index.js
Module not found: Error: Can't resolve 'stream' in '/project-directory/node_modules/cipher-base'
ERROR in ./node_modules/hash-base/index.js
Module not found: Error: Can't resolve 'stream' in '/project-directory/node_modules/hash-base'
ERROR in ./src/polyfills.ts
Module not found: Error: Can't resolve 'stream' in '/project-directory/src'

Anybody able to make this work without monkey patching?

zone117x commented 4 years ago

stream would be a hard to lib to remove because of all the downstream dependencies.

Can you specify it as a node polyfill?

module.exports = {
  //...
  node: {
    stream: true,
  }
};

https://webpack.js.org/configuration/node/

kyranjamie commented 4 years ago

Just had another look into this, as the @blockstack/connect package is also affected. The above you've shared @zone117x doesn't play well with angular cli as it doesn't expose the webpack config.

As @johannesjo pointed out the issue is the dependency on node's internal stream via the cipher-base package. This can be addressed using tsconfig paths in your Angular project, pointing to the readable-stream polyfill package.

  "compilerOptions": {
    "paths": {
      "stream": ["./node_modules/readable-stream"]
    }
  },

I've made a demo repo that highlights 3 of the main workarounds required

Longer term, I think the solution is for blockstack.js to handle these polyfills internally, outputting separate node & browser bundles.

markmhendrickson commented 4 years ago

I got this to work for an Ember app with ember-auto-import by configuring my ember-cli-build.js file as such:

'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  let app = new EmberApp(defaults, {
    autoImport: {
      webpack: {
        node: {
          stream: true
        }
      }
    }
  });
  return app.toTree();
};
friedger commented 3 years ago

A new guide is coming: https://github.com/blockstack/docs/pull/878

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

This issue has been automatically closed. Please reopen if needed.