Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doesn't work in Angular / Web #1242

Open
AndreasGassmann opened this issue Nov 13, 2023 · 4 comments
Open

Doesn't work in Angular / Web #1242

AndreasGassmann opened this issue Nov 13, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@AndreasGassmann
Copy link

As part of the Mina Navigators Hackathon, we built a project with multiple components. We used o1js successfully in the backend to create and deploy a contract. However, we struggled to use o1js in a frontend, created with the Angular framework.

After doing npm i o1js and trying to use it, this was the error:

import { PublicKey } from 'o1js';
Error message
Error: node_modules/o1js/dist/node/bindings/crypto/bindings/curve.d.ts:4:24 - error TS2307: Cannot find module 'src/lib/ml/base.js' or its corresponding type declarations.

4 import { MlPair } from 'src/lib/ml/base.js';
                         ~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/node/bindings/crypto/bindings/kimchi-types.d.ts:8:43 - error TS2307: Cannot find module '../../compiled/node_bindings/plonk_wasm.cjs' or its corresponding type declarations.

8 import type { WasmFpSrs, WasmFqSrs } from '../../compiled/node_bindings/plonk_wasm.cjs';
                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/node/bindings/js/node/node-backend.d.ts:4:34 - error TS2307: Cannot find module '../../compiled/node_bindings/plonk_wasm.cjs' or its corresponding type declarations.

4 export const wasm: typeof import("../../compiled/node_bindings/plonk_wasm.cjs");
                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/node/bindings/js/wrapper.d.ts:2:42 - error TS2307: Cannot find module '../compiled/node_bindings/plonk_wasm.cjs' or its corresponding type declarations.

2 export function getWasm(): typeof import("../compiled/node_bindings/plonk_wasm.cjs");
                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/node/lib/proof-system/prover-keys.d.ts:8:62 - error TS2307: Cannot find module '../../bindings/compiled/node_bindings/plonk_wasm.cjs' or its corresponding type declarations.

8 import { WasmPastaFpPlonkIndex, WasmPastaFqPlonkIndex } from '../../bindings/compiled/node_bindings/plonk_wasm.cjs';
                                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/node/snarky.d.ts:27:8 - error TS2307: Cannot find module './bindings/compiled/node_bindings/plonk_wasm.cjs' or its corresponding type declarations.

27 } from './bindings/compiled/node_bindings/plonk_wasm.cjs';
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I then tried to import the web part directly, but there were even more errors.

import { PublicKey } from 'o1js/dist/web';
Error message
./src/app/app.component.ts:1:0-42 - Error: Module not found: Error: Package path ./dist/web is not exported from package /Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js (see exports field in /Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/package.json)

Error: node_modules/o1js/dist/web/bindings/lib/provable-snarky.d.ts:1:10 - error TS2305: Module '"../../snarky.js"' has no exported member 'Provable'.

1 import { Provable, ProvablePure } from '../../snarky.js';
           ~~~~~~~~


Error: node_modules/o1js/dist/web/bindings/lib/provable-snarky.d.ts:1:20 - error TS2305: Module '"../../snarky.js"' has no exported member 'ProvablePure'.

1 import { Provable, ProvablePure } from '../../snarky.js';
                     ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/index.d.ts:1:15 - error TS2305: Module '"./snarky.js"' has no exported member 'ProvablePure'.

1 export type { ProvablePure } from './snarky.js';
                ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/account_update.d.ts:316:21 - error TS2503: Cannot find namespace 'Pickles'.

316     previousProofs: Pickles.Proof[];
                        ~~~~~~~


Error: node_modules/o1js/dist/web/lib/account_update.d.ts:734:38 - error TS2694: Namespace '"/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/snarky"' has no exported member 'ProvablePure'.

734         type: import("../snarky.js").ProvablePure<{
                                         ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/account_update.d.ts:807:47 - error TS2694: Namespace '"/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/snarky"' has no exported member 'ProvablePure'.

807     callerContextType: import("../snarky.js").ProvablePure<{
                                                  ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/account_update.d.ts:896:54 - error TS2694: Namespace '"/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/snarky"' has no exported member 'ProvablePure'.

896 declare let ZkappPublicInput: import("../snarky.js").ProvablePure<{
                                                         ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:1:10 - error TS2305: Module '"../snarky.js"' has no exported member 'ProvablePure'.

1 import { ProvablePure, Snarky } from '../snarky.js';
           ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:101:12 - error TS2503: Cannot find namespace 'Snarky'.

101     value: Snarky.Keypair;
               ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:102:24 - error TS2503: Cannot find namespace 'Snarky'.

102     constructor(value: Snarky.Keypair);
                           ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:113:48 - error TS2694: Namespace '"/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/snarky"' has no exported member 'Gate'.

113     constraintSystem(): import("../snarky.js").Gate[];
                                                   ~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:119:12 - error TS2503: Cannot find namespace 'Snarky'.

119     value: Snarky.Proof;
               ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:120:24 - error TS2503: Cannot find namespace 'Snarky'.

120     constructor(value: Snarky.Proof);
                           ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:126:12 - error TS2503: Cannot find namespace 'Snarky'.

126     value: Snarky.VerificationKey;
               ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit.d.ts:127:24 - error TS2503: Cannot find namespace 'Snarky'.

127     constructor(value: Snarky.VerificationKey);
                           ~~~~~~


Error: node_modules/o1js/dist/web/lib/circuit_value.d.ts:2:10 - error TS2305: Module '"../snarky.js"' has no exported member 'ProvablePure'.

2 import { ProvablePure } from '../snarky.js';
           ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/nullifier.d.ts:30:28 - error TS2694: Namespace '"/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/snarky"' has no exported member 'ProvablePure'.

30 } & import("../snarky.js").ProvablePure<{
                              ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:1:10 - error TS2305: Module '"../snarky.js"' has no exported member 'ProvablePure'.

1 import { ProvablePure, Pickles, Gate } from '../snarky.js';
           ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:1:33 - error TS2305: Module '"../snarky.js"' has no exported member 'Gate'.

1 import { ProvablePure, Pickles, Gate } from '../snarky.js';
                                  ~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:23:12 - error TS2503: Cannot find namespace 'Pickles'.

23     proof: Pickles.Proof;
              ~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:31:16 - error TS2503: Cannot find namespace 'Pickles'.

31         proof: Pickles.Proof;
                  ~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:186:14 - error TS2503: Cannot find namespace 'Pickles'.

186     provers: Pickles.Prover[];
                 ~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:187:25 - error TS2503: Cannot find namespace 'Pickles'.

187     verify: (statement: Pickles.Statement<FieldConst>, proof: Pickles.Proof) => Promise<boolean>;
                            ~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:187:63 - error TS2503: Cannot find namespace 'Pickles'.

187     verify: (statement: Pickles.Statement<FieldConst>, proof: Pickles.Proof) => Promise<boolean>;
                                                                  ~~~~~~~


Error: node_modules/o1js/dist/web/lib/proof_system.d.ts:199:86 - error TS2503: Cannot find namespace 'Pickles'.

199 }, { methodName, witnessArgs, proofArgs, allArgs }: MethodInterface, gates: Gate[]): Pickles.Rule;
                                                                                         ~~~~~~~


Error: node_modules/o1js/dist/web/lib/provable-context.d.ts:2:10 - error TS2305: Module '"../snarky.js"' has no exported member 'Gate'.

2 import { Gate, JsonGate } from '../snarky.js';
           ~~~~


Error: node_modules/o1js/dist/web/lib/provable-context.d.ts:2:16 - error TS2305: Module '"../snarky.js"' has no exported member 'JsonGate'.

2 import { Gate, JsonGate } from '../snarky.js';
                 ~~~~~~~~


Error: node_modules/o1js/dist/web/lib/provable.d.ts:7:10 - error TS2305: Module '"../snarky.js"' has no exported member 'Provable'.

7 import { Provable as Provable_ } from '../snarky.js';
           ~~~~~~~~


Error: node_modules/o1js/dist/web/lib/zkapp.d.ts:1:10 - error TS2305: Module '"../snarky.js"' has no exported member 'Gate'.

1 import { Gate, Pickles, ProvablePure } from '../snarky.js';
           ~~~~


Error: node_modules/o1js/dist/web/lib/zkapp.d.ts:1:25 - error TS2305: Module '"../snarky.js"' has no exported member 'ProvablePure'.

1 import { Gate, Pickles, ProvablePure } from '../snarky.js';
                          ~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/lib/zkapp.d.ts:57:23 - error TS2503: Cannot find namespace 'Pickles'.

57     static _provers?: Pickles.Prover[];
                         ~~~~~~~


Error: node_modules/o1js/dist/web/lib/zkapp.d.ts:146:18 - error TS2503: Cannot find namespace 'Pickles'.

146         provers: Pickles.Prover[];
                     ~~~~~~~


Error: node_modules/o1js/dist/web/lib/zkapp.d.ts:147:29 - error TS2503: Cannot find namespace 'Pickles'.

147         verify: (statement: Pickles.Statement<import("./field.js").FieldConst>, proof: unknown) => Promise<boolean>;
                                ~~~~~~~


Error: node_modules/o1js/dist/web/snarky.d.ts:5:32 - error TS7016: Could not find a declaration file for module './bindings/js/wrapper.js'. '/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/bindings/js/wrapper.js' implicitly has an 'any' type.

5 import { withThreadPool } from './bindings/js/wrapper.js';
                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/o1js/dist/web/snarky.d.ts:6:25 - error TS7016: Could not find a declaration file for module './bindings/js/wrapper.js'. '/Users/main/Programming/Personal/mina-zk-hack/frontend/node_modules/o1js/dist/web/bindings/js/wrapper.js' implicitly has an 'any' type.

6 import { getWasm } from './bindings/js/wrapper.js';
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~

So I went back to the original import { PublicKey } from 'o1js' and fixed the error. There seem to be some invalid paths, which I was able to address by creating this script:

const fs = require("fs");

const replaceInFile = (filePath, searchString, replaceString) => {
  // Read file
  fs.readFile(filePath, "utf8", (err, data) => {
    if (err) {
      console.error(err);
      return;
    }

    // Replace string
    const result = data.replace(new RegExp(searchString, "g"), replaceString);

    // Save file
    fs.writeFile(filePath, result, "utf8", (err) => {
      if (err) {
        console.error(err);
      } else {
        console.log("File successfully updated");
      }
    });
  });
};

replaceInFile(
  "node_modules/o1js/dist/node/bindings/crypto/bindings/curve.d.ts",
  "import { MlPair } from 'src/lib/ml/base.js';",
  "import { MlPair } from '../../../lib/ml/base.js';"
);
replaceInFile(
  "node_modules/o1js/dist/node/bindings/crypto/bindings/kimchi-types.d.ts",
  "import type { WasmFpSrs, WasmFqSrs } from '../../compiled/node_bindings/plonk_wasm.cjs';",
  "import type { WasmFpSrs, WasmFqSrs } from '../../compiled/_node_bindings/plonk_wasm.cjs';"
);
replaceInFile(
  "node_modules/o1js/dist/node/bindings/js/node/node-backend.d.ts",
  "../../compiled/node_bindings/plonk_wasm.cjs",
  "../../compiled/_node_bindings/plonk_wasm.cjs"
);
replaceInFile(
  "node_modules/o1js/dist/node/bindings/js/wrapper.d.ts",
  "../compiled/node_bindings/plonk_wasm.cjs",
  "../compiled/_node_bindings/plonk_wasm.cjs"
);
replaceInFile(
  "node_modules/o1js/dist/node/lib/proof-system/prover-keys.d.ts",
  "import { WasmPastaFpPlonkIndex, WasmPastaFqPlonkIndex } from '../../bindings/compiled/node_bindings/plonk_wasm.cjs';",
  "import { WasmPastaFpPlonkIndex, WasmPastaFqPlonkIndex } from '../../bindings/compiled/_node_bindings/plonk_wasm.cjs';"
);
replaceInFile(
  "node_modules/o1js/dist/node/snarky.d.ts",
  "} from './bindings/compiled/node_bindings/plonk_wasm.cjs';",
  "} from './bindings/compiled/_node_bindings/plonk_wasm.cjs';"
);

With this "fix", I was able to run the page. However, there were some new errors:

Unhandled Promise rejection: Failed to execute 'postMessage' on 'Worker': SharedArrayBuffer transfer requires self.crossOriginIsolated. ; Zone: <root> ; Task: Promise.then ; Value: DOMException: Failed to execute 'postMessage' on 'Worker': SharedArrayBuffer transfer requires self.crossOriginIsolated.
    at http://localhost:4200/vendor.js:88866:14
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (http://localhost:4200/vendor.js:103024:24)
    at _next (http://localhost:4200/vendor.js:103043:9)
    at http://localhost:4200/vendor.js:103048:7
    at new ZoneAwarePromise (http://localhost:4200/polyfills.js:9222:21)
    at http://localhost:4200/vendor.js:103040:12
    at _hr (http://localhost:4200/vendor.js:88872:14)
    at hr (http://localhost:4200/vendor.js:88860:14)
    at http://localhost:4200/vendor.js:88744:15
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (http://localhost:4200/vendor.js:103024:24)
    at _next (http://localhost:4200/vendor.js:103043:9)
    at http://localhost:4200/vendor.js:103048:7
    at new ZoneAwarePromise (http://localhost:4200/polyfills.js:9222:21)
    at http://localhost:4200/vendor.js:103040:12
    at timer (http://localhost:4200/polyfills.js:10151:27)
    at _ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8236:171)
    at Zone.runTask (http://localhost:4200/polyfills.js:8040:37)
    at invokeTask (http://localhost:4200/polyfills.js:8313:26)
    at ZoneTask.invoke (http://localhost:4200/polyfills.js:8302:38)
    at data.args.<computed> (http://localhost:4200/polyfills.js:10133:26)

And also this:

Uncaught ReferenceError: _VB is not defined
    at VB (7781500a-ba12-4c67-8e65-abfacf023bba:6394:3)
    at 7781500a-ba12-4c67-8e65-abfacf023bba:6397:1

But even with those errors, o1js seems to work as it was able to create a PublicKey. I then went ahead and imported the SmartContract class I created, but then the whole thing breaks completely, again.

app.component.html:426 Unhandled Promise rejection: Cannot read properties of undefined (reading 'length') ; Zone: <root> ; Task: null ; Value: TypeError: Cannot read properties of undefined (reading 'length')
    at Ye (index.js:2080:6084)
    at bQ (index.js:2250:720)
    at H (index.js:2076:3366)
    at Reflect.G (index.js:2076:2062)
    at __decorate (tslib:57:1)
    at AcurastPriceOracle.ts:47:11 TypeError: Cannot read properties of undefined (reading 'length')
    at Ye (http://localhost:4200/vendor.js:30978:25)
    at bQ (http://localhost:4200/vendor.js:32436:11)
    at H (http://localhost:4200/vendor.js:25225:16)
    at Reflect.G (http://localhost:4200/vendor.js:25153:50)
    at __decorate (http://localhost:4200/vendor.js:127351:90)
    at http://localhost:4200/main.js:85:50

That's the contract I tried to interact with:

https://github.com/Acurast/mina-zkoracles/blob/main/contracts/src/AcurastPriceOracle.ts#L47

export class AcurastPriceOracle extends SmartContract {
  ...

  init() {
    super.init();
    ...
  }

  @method update( // <- Error happens here
    nextCounter: Field,
    priceDataBTC: Field,
    priceDataETH: Field,
    priceDataMINA: Field,
    signature: Signature
  ) {
    ...
  }
}

That's where I gave up and used the GraphQL API to fetch the contract state.

Another part of our application is that we would like to deploy a smart contract directly from the frontend. For this, it seems we could use SmartContract.compile() together with SmartContract.deploy(...).

Any help would be appreciated.

PS: There is another issue open about issues with Angular, but I don't think it's directly related, so I opened a new one: #910

@dfstio
Copy link

dfstio commented Nov 14, 2023

I would recommend to compare backend and web TypeScript settings, in particular:

 "compilerOptions": {
    "composite": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strictPropertyInitialization": false
    }

@mitschabaude mitschabaude added the bug Something isn't working label Nov 18, 2023
@IsaccoSordo
Copy link

Hi all,
the build will still fail even after adding those lines in tsconfig.json, the errors are the same as @AndreasGassmann

@dfstio
Copy link

dfstio commented Dec 4, 2023

You can also try to downgrade typescript libraries; I've seen the same errors after upgrading to the last versions:
https://discord.com/channels/484437221055922177/1176450974873813073/1177569477521584179

@directcuteo
Copy link

@AndreasGassmann After a lot of time spent with the same issue in Angular I came to a bunch of conclusions:

  1. It works fine if you build a simple Javascript(+Typescript) + Webpack application and run it there
  2. It doesn't work in Angular + Webpack environment (which is 99.9% of Angular projects)
  3. It works in Angular + Vite environment (which is hard to configure) and has some tradeoffs from Angular side (harder development process).
  4. o1js relies on topLevelAwait feature. Angular by its own rules doesn't come with topLevelAwait as a default configuration and therefore it is not considered a bug if something dependent on that is not working. The flag is enabled there by Webpack, not by Angular, they take no responsibility.

o1js is doing some really strange function-string operations with the WebWorkers which most probably confuses Angular and the mechanisms underneath. I think that with Angular's latest release (v17), the o1js team should prioritize the support for Angular because it is getting more popular than ever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants