From ea05208f88adcbc9911cf24eb589cade7aad7d7a Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:45:09 +0800 Subject: [PATCH 1/7] add the angular integration guide --- .../front-end-integration-guides/angular.mdx | 424 ++++++++++++++++++ sidebars.js | 11 + 2 files changed, 435 insertions(+) create mode 100644 docs/zkapps/front-end-integration-guides/angular.mdx diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx new file mode 100644 index 000000000..cfbeebfdc --- /dev/null +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -0,0 +1,424 @@ +--- +title: Angular and Github Pages +description: Getting started with Angular +keywords: + - angular + - ui + - sharedarraybuffer +--- + +# Angular Integration Guide +## Install a Wallet + +- Install a wallet that supports zkApp transactions. For this tutorial, we’ll use **Auro Wallet**. [Download it here](https://www.aurowallet.com/). +- Add the Auro Wallet browser extension. +- Open the extension and follow the steps to create a new wallet. +- Click **"Mainnet"** at the top of the extension view, then select **Show Testnet** from the menu. After that, select **Devnet**. + - Using Devnet will allow us to interact with a test version of the Mina network without needing to spend real Mina to pay for transaction fees. +- Fund your wallet using the [Mina Faucet](https://faucet.minaprotocol.com/). + - You'll need to wait about 3 minutes to see the change in balance reflected on chain. You can use [Minascan](https://minascan.io/devnet) to track the status of your transaction. + +## Initialize the Project + +- Install the Angular cli globally: + +```bash +npm install -g @angular/cli +``` + +- Create a new Angular project by running: + +```bash +ng new +``` + +- Install the Angular cli `npm install -g @angular/cli` +- Create a new project `ng new ` + - Select your preferred stylesheet format. + - For **Server-Side Rendering (SSR)** and **Static Site Generation (SSG/Prerendering)**, choose **Yes**. +- Install the `o1js` library: + +```bash +cd +npm install o1js +``` + +- Start the local development server. + - This command runs `ng serve` which we will further configure by changing `options` under the `serve` build target in `angular.json` + +```bash +npm run start +``` + +## Create the ZkApp Contract + +- Navigate out of the demo project directory and install the `zkapp-cli` globally: + +```bash +cd ../ +npm install -g zkapp-cli +``` + +- Initialize a new zkapp with the cli. When prompted to create a UI project, select **none**. + +```bash +zk project add +``` + +- Change into the newly created `add` directory and build the contract: + +```bash +cd add +npm run build +``` + +- We've already deployed an instance of the default `Add` contract to Devnet at [B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5](https://minascan.io/devnet/account/B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5) so you won't need to deploy the contract you just created. You'll still need to include the contract code in your project so that it can be compiled into a verification key and proving key. + - The proving key enables users to generate proofs of valid contract execution directly in their browsers. A user can run a contract call locally, create a proof of its execution using the proving key, and then publish the proof on-chain to update the zkApp’s state. Since the verification key is stored on-chain, the network will accept a transaction sent to this address if it includes a proof generated with the proving key that matches the on-chain verification key. + +## Call Contracts + +- Move back into the angular project +- To interact with the deployed `Add` contract, we’ll add code to fetch the current state and initiate a transaction. This code will execute only in the browser, so we'll add it to `afterNextRender` in the constructor of `src/app/app.component.ts`. + - `afterNextRender` only runs after the Angular component has fully rendered + - The Auro wallet injects a Mina provider into the global context. It is accessible as `window.mina`. + +```tsx +import {afterNextRender, Component} from '@angular/core'; +import {RouterOutlet} from '@angular/router'; + +@Component({ + selector: 'app-root', + standalone: true, + imports: [RouterOutlet], + templateUrl: './app.component.html', + styleUrl: './app.component.scss' +}) + +export class AppComponent { + title = 'angular-o1js-demo'; + + constructor() { + afterNextRender(async () => { + const {Mina, PublicKey, fetchAccount} = await import('o1js'); + const {Add} = await import('../../../add'); + // connect the Mina instance to testnet +Mina.setActiveInstance(Mina.Network('')); + // we've already deployed the Add contract on testnet at this address + // +const zkAppAddress = `B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5`; + await fetchAccount({publicKey: zkAppAddress}); + const zkApp = new Add(PublicKey.fromBase58(zkAppAddress)); + // Read state from the testnet Add contract +console.log(`Reading state of add contract at ${zkAppAddress}: num=${zkApp.num.get()}`); + try { + // retrieve the injected mina provider if it exists +const mina = (window as any).mina; + const walletKey: string = (await mina.requestAccounts())[0]; + console.log(`Injected mina provider address: ${walletKey}`); + await fetchAccount({publicKey: PublicKey.fromBase58(walletKey)}); + console.log("Compiling Add"); + await Add.compile(); + console.log("Compiled Add"); + + // send a transaction with the injected Mina provider +const transaction = await Mina.transaction(async () => { + await zkApp.update(); + }); + await transaction.prove(); + const {hash} = await (window as any).mina.sendTransaction({ + transaction: transaction.toJSON(), + }); + + // display the link to the transaction +const transactionLink = `https://minascan.io/devnet/tx/${hash}`; + console.log(`View transaction at ${transactionLink}`); + } catch (e: any) { + console.error(e.message); + + switch (e.message) { + case e.message.includes("Cannot read properties of undefined (reading 'requestAccounts')"): + console.error("Is Auro installed?"); + break; + case e.message.includes("Please create or restore wallet first."): + console.error("Have you created a wallet?"); + break; + case e.message.includes("User rejected the request."): + console.error("Did you grant the app permission to connect to your wallet?"); + break; + default: + console.error("An unknown error occurred:", e); + } + } + }); + } +} + +``` + +- The above code: + - Connects Mina to a Devnet node so transactions are broadcasted to Devnet + - Requests the user's address from the mina provider injected into the browser context by the wallet + - Compiles the `Add` zkApp contract to generate and cache the proving key, which will allow the app to create proofs for transactions. + - Creates a zkapp transaction calling `update` on the `Add` contract + - Proves the transaction using the proving key which o1js has internally cached + - Prompts the user to broadcast the transaction to the network with their wallet +- Now run the application in your browser with `npm run start` (which executes `ng serve`) and open the browser console. + - Approve the connection request displayed in Auro. + +## SharedArrayBuffer Headers for `ng serve` + +- You'll see that some of the code works, like the on-chain state retrieval, but compiling a zkapp fails with `DataCloneError: Failed to execute 'postMessage' on 'Worker': SharedArrayBuffer transfer requires self.crossOriginIsolated`. +- `SharedArrayBuffer` is a JavaScript object that lets different threads share memory. Since o1js's proving is very computationally intensive, we us WASM workers for parallel processing in the browser. +- For security reasons, `SharedArrayBuffer` needs certain headers to be set. These prevent cross origin resources (scripts and content loaded from external domains, iframes, and popups) from accessing shared memory. + - Cross-Origin-Opener-Policy (COOP) must be set to `"same-origin"` to prevents cross-origin resources from accessing the main document’s memory. + - Cross-Origin-Embedder-Policy (COEP) must be set to `"require-corp"` to restrict the way cross origin resources can be loaded by the main document. They'll either need to be from the same origin or include the `Cross-Origin-Resource-Policy: cross-origin` header. +- Depending on how the application is being run, there are different ways to set these headers. Running the application locally with `ng serve` uses `@angular-devkit/build-angular:dev-server"` which we can configure in the project's `angular.json` file at `/projects/angular-o1js-demo/architect/serve/configurations/development` +- Architect is angular's task runner, the entries (called build targets) under `architect` each represent tasks that the angular cli can run (`ng build`, `ng serve`, `ng test`, etc). The `builder` property of each target specifies the program that Architect should run to execute the task. The `options` can be used to supply parameters to the builder, and the `configurations`specifies a custom set of options for different target configurations (development, production, etc). +- Running `ng serve` locally runs the `@angular-devkit/build-angular:dev-server` builder, and in its options object we can specify custom headers specifying the headers required for `SharedArrayBuffer` as follows: + +``` + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "headers": { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp" + } + }, +``` + +- Restart the server with `npm run start` and view the application in the browser again - the `SharedArrayBuffer` error should be gone! + +## Loading o1js + +- We still have another error: `Uncaught ReferenceError: __async is not defined` +- This one comes from the way Angular bundles dependencies internally. We'll address it by supplying our own custom webpack config which will exclude o1js from the bundle generated by Angular. Then we'll copy o1js into our static assets directory so it's served with the app and use import maps to import o1js directly. + +### Create a Custom Webpack Config + +- Start by creating a custom webpack config by adding a file `webpack.config.js` at the root of your project with the following contents: + +```jsx +module.exports = { + externals: { + 'o1js': 'o1js' + } +}; +``` + +### Update Builders to Use Custom Webpack + +- Install builders which support using custom webpack configs - Angular's default builder will ignore the webpack file + +```bash +npm i @angular-builders/custom-webpack +``` + +- Update the `serve` and `build` build targets to use the `@angular-builders/custom-webpack` builders and load the file + - In `angular.json` under `/projects/angular-o1js-demo/architect/build`, replace the default builder `"builder": "@angular-devkit/build-angular:application",` with `"builder": "@angular-builders/custom-webpack:browser",` + - rename the browser property to `main` in `options` + - add `"customWebpackConfig": { "path": "./webpack.config.js" },` to `options` + - delete `server`, `prerender`, and `ssr` from `options` + - In `angular.json` under `/projects/angular-o1js-demo/architect/serve`, replace the default builder `"builder": "@angular-devkit/build-angular:dev-server",` with ` "builder": "@angular-builders/custom-webpack:dev-server", +- The build targets should look like this: + +```json +"build": { + "builder": "@angular-builders/custom-webpack:browser", + "options": { + "customWebpackConfig": { + "path": "./webpack.config.js" + }, + "main": "src/main.ts", + "outputPath": "dist/", + "index": "src/index.html", + "polyfills": [ + "zone.js" + ], + "tsConfig": "tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "public" + } + ], + "styles": [ + "src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kB", + "maximumError": "1MB" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kB", + "maximumError": "4kB" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" +}, +"serve": { + "builder": "@angular-builders/custom-webpack:dev-server", + "configurations": { + "production": { + "buildTarget": ":build:production" + }, + "development": { + "buildTarget": ":build:development" + } + }, + "options": { + "headers": { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp" + } + }, + "defaultConfiguration": "development" +}, +``` + +### Copy o1js into Static Assets + +- Now we'll write a script to copy o1js into `public` where our static assets are served along with the application and then import it directly with an `importmap` +- Add a script to `package.json` that copies o1js from `node_modules` to a new directory at `public/lib/o1js`. + - Files under public are served with the app, so the file itself will be available at http://localhost:4200/lib/o1js/index.js + +```json +"copy-libs": "mkdir -p public/lib/o1js && cp node_modules/o1js/dist/web/index.js public/lib/o1js/index.js" +``` + +- add the `copy-o1js-lib` task to the build script and the start script + - `"build": "npm run copy-libs && ng build",` + - `"start": "npm run copy-libs && ng serve",` +- Add `public/lib` to `.gitignore` + +### Load o1js with an `importmap` + +- Above the closing `` tag in `src/index.html` add these scripts to import o1js from `public/lib/o1js`: + +```html +... + + + +``` + +- Now instead of importing o1js as a regular npm dependency, we declare it as a top level variable in app component knowing that it will exist in the global context of the browser at runtime. Add the following to the top of `src/app.component.ts`: + +```tsx +// at the top of the file: +import type * as o1jsTypes from 'o1js'; +declare var o1js: typeof o1jsTypes; +``` + +- Remove the import of o1js inside of `afterNextRender` and replace it with this: + +```tsx +const {Mina, PublicKey, fetchAccount} = o1js; +``` + +## Running the App Locally + +- Congratulations! The app should work as expected when served with `npm run start` (`ng serve`). +- Restart the application with `npm run start`. +- Verify that `Set the global o1js instance: Module {…}` was logged in the console, indicating that o1js was successfully loaded from our public assets. +- Verify that the current `num` on the `Add` zkapp is logged, meaning that we're successfully reading state from the contract at `B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5` on Devnet. +- Verify that "Compiled Add" is logged, meaning that the SDK has successfully generated a proving key for the `Add` zkapp. +- If you're connected to Devnet and your account is funded with Devnet tokens, you should be be able to broadcast a successful transaction calling `update` on the zkapp. After a few minutes, the state change associated with the transaction will take effect on chain and you'll see `num` increase when you reload the page! + +## Deploying to Github Pages + +- Now we'll set the app up for deployment to github pages. +- Publish your project to a GitHub repository. +- Run `ng deploy` and select GitHub Pages +- Add `baseHref` to `options` under `build` in angular.json with the name of your github repository. + - **Do not remove the slashes!** + +```json +"baseHref": "//" +``` + +- Create a deploy script in package.json which copies the required libraries + +```json +"deploy": "npm run copy-libs && ng deploy --dir=dist/" +``` + +- Deploy the app. + +```bash +npm run deploy +``` + +- You can view deployment details at `https://github.com///actions` and your live site at `https://.github.io//`. + +## SharedArrayBuffer in Deployed Instance + +- View the site and open the browser console. You'll see the same error about the SharedArrayBuffer from before! The headers set previously apply only to `ng serve`, so we’ll set them up for GitHub Pages. +- Install `coi-serviceworker` + +```bash +npm i coi-serviceworker +``` + +- Update the script that copies `o1js` to `public` to also include the `coi-serviceworker` file: + +```json +"copy-libs": "mkdir -p public/lib/o1js && cp node_modules/o1js/dist/web/index.js public/lib/o1js/index.js && cp node_modules/coi-serviceworker/coi-serviceworker.min.js public/lib/coi-serviceworker.min.js" +``` + +- Create a file `src/app/COIServiceWorker.ts` with the following contents + - Be sure to replace \ with the name of your github repo! + +```tsx +export {}; + +function loadCOIServiceWorker() { + console.log('Load COIServiceWorker', navigator); + if (typeof window !== 'undefined' && 'serviceWorker' in navigator && window.location.hostname != 'localhost') { + navigator.serviceWorker.register('//lib/coi-serviceworker.min.js') + .then(registration => console.log('COI Service Worker registered with scope:', registration.scope)) + .catch(error => console.error('COI Service Worker registration failed:', error)); + } +} + +loadCOIServiceWorker(); +``` + +- Import it at the top of `src/app/app.component.ts` + +```tsx +import './COIServiceWorker'; +``` + +- Redeploy the application with the `COIServiceWorker` files. + +```bash +npm run deploy +``` + +## Congratulations, you’ve developed and deployed a zkApp UI with Angular! + +Next steps include learning to use web workers to prevent computationally expensive operations like `compile` from blocking the UI thread, handling events, and building more complex zkApp contracts! + diff --git a/sidebars.js b/sidebars.js index 031875801..72c2aa286 100644 --- a/sidebars.js +++ b/sidebars.js @@ -143,6 +143,17 @@ module.exports = { 'zkapps/advanced/zkapps-for-ethereum-developers', ], }, + { + type: 'category', + label: 'Front End Integration Guides', + link: { + type: 'doc', + id: 'zkapps/front-end-integration-guides/angular', + }, + items: [ + 'zkapps/front-end-integration-guides/angular', + ], + }, { type: 'category', label: 'Tutorials', From 0c07d5fc6f49cd7d34ba999bb568c7be7b3e9c18 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:31:33 +0800 Subject: [PATCH 2/7] apply minor formatting changes --- .../front-end-integration-guides/angular.mdx | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index cfbeebfdc..34fc3548a 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -44,7 +44,7 @@ npm install o1js ``` - Start the local development server. - - This command runs `ng serve` which we will further configure by changing `options` under the `serve` build target in `angular.json` + - This command runs `ng serve` which we will further configure by changing `options` under the `serve` build target in `angular.json`. ```bash npm run start @@ -77,9 +77,9 @@ npm run build ## Call Contracts -- Move back into the angular project +- Move back into the angular project. - To interact with the deployed `Add` contract, we’ll add code to fetch the current state and initiate a transaction. This code will execute only in the browser, so we'll add it to `afterNextRender` in the constructor of `src/app/app.component.ts`. - - `afterNextRender` only runs after the Angular component has fully rendered + - `afterNextRender` only runs after the Angular component has fully rendered. - The Auro wallet injects a Mina provider into the global context. It is accessible as `window.mina`. ```tsx @@ -156,12 +156,12 @@ const transactionLink = `https://minascan.io/devnet/tx/${hash}`; ``` - The above code: - - Connects Mina to a Devnet node so transactions are broadcasted to Devnet - - Requests the user's address from the mina provider injected into the browser context by the wallet + - Connects Mina to a Devnet node so transactions are broadcasted to Devnet. + - Requests the user's address from the mina provider injected into the browser context by the wallet. - Compiles the `Add` zkApp contract to generate and cache the proving key, which will allow the app to create proofs for transactions. - - Creates a zkapp transaction calling `update` on the `Add` contract - - Proves the transaction using the proving key which o1js has internally cached - - Prompts the user to broadcast the transaction to the network with their wallet + - Creates a zkapp transaction calling `update` on the `Add` contract. + - Proves the transaction using the proving key which o1js has internally cached. + - Prompts the user to broadcast the transaction to the network with their wallet. - Now run the application in your browser with `npm run start` (which executes `ng serve`) and open the browser console. - Approve the connection request displayed in Auro. @@ -172,7 +172,7 @@ const transactionLink = `https://minascan.io/devnet/tx/${hash}`; - For security reasons, `SharedArrayBuffer` needs certain headers to be set. These prevent cross origin resources (scripts and content loaded from external domains, iframes, and popups) from accessing shared memory. - Cross-Origin-Opener-Policy (COOP) must be set to `"same-origin"` to prevents cross-origin resources from accessing the main document’s memory. - Cross-Origin-Embedder-Policy (COEP) must be set to `"require-corp"` to restrict the way cross origin resources can be loaded by the main document. They'll either need to be from the same origin or include the `Cross-Origin-Resource-Policy: cross-origin` header. -- Depending on how the application is being run, there are different ways to set these headers. Running the application locally with `ng serve` uses `@angular-devkit/build-angular:dev-server"` which we can configure in the project's `angular.json` file at `/projects/angular-o1js-demo/architect/serve/configurations/development` +- Depending on how the application is being run, there are different ways to set these headers. Running the application locally with `ng serve` uses `@angular-devkit/build-angular:dev-server"` which we can configure in the project's `angular.json` file at `/projects/angular-o1js-demo/architect/serve/configurations/development`. - Architect is angular's task runner, the entries (called build targets) under `architect` each represent tasks that the angular cli can run (`ng build`, `ng serve`, `ng test`, etc). The `builder` property of each target specifies the program that Architect should run to execute the task. The `options` can be used to supply parameters to the builder, and the `configurations`specifies a custom set of options for different target configurations (development, production, etc). - Running `ng serve` locally runs the `@angular-devkit/build-angular:dev-server` builder, and in its options object we can specify custom headers specifying the headers required for `SharedArrayBuffer` as follows: @@ -191,7 +191,7 @@ const transactionLink = `https://minascan.io/devnet/tx/${hash}`; ## Loading o1js -- We still have another error: `Uncaught ReferenceError: __async is not defined` +- We still have another error: `Uncaught ReferenceError: __async is not defined`. - This one comes from the way Angular bundles dependencies internally. We'll address it by supplying our own custom webpack config which will exclude o1js from the bundle generated by Angular. Then we'll copy o1js into our static assets directory so it's served with the app and use import maps to import o1js directly. ### Create a Custom Webpack Config @@ -208,18 +208,18 @@ module.exports = { ### Update Builders to Use Custom Webpack -- Install builders which support using custom webpack configs - Angular's default builder will ignore the webpack file +- Install builders which support using custom webpack configs - Angular's default builder will ignore the webpack file. ```bash npm i @angular-builders/custom-webpack ``` -- Update the `serve` and `build` build targets to use the `@angular-builders/custom-webpack` builders and load the file - - In `angular.json` under `/projects/angular-o1js-demo/architect/build`, replace the default builder `"builder": "@angular-devkit/build-angular:application",` with `"builder": "@angular-builders/custom-webpack:browser",` - - rename the browser property to `main` in `options` - - add `"customWebpackConfig": { "path": "./webpack.config.js" },` to `options` - - delete `server`, `prerender`, and `ssr` from `options` - - In `angular.json` under `/projects/angular-o1js-demo/architect/serve`, replace the default builder `"builder": "@angular-devkit/build-angular:dev-server",` with ` "builder": "@angular-builders/custom-webpack:dev-server", +- Update the `serve` and `build` build targets to use the `@angular-builders/custom-webpack` builders and load the file. + - In `angular.json` under `/projects/angular-o1js-demo/architect/build`, replace the default builder `"builder": "@angular-devkit/build-angular:application",` with `"builder": "@angular-builders/custom-webpack:browser"`. + - rename the browser property to `main` in `options`. + - add `"customWebpackConfig": { "path": "./webpack.config.js" },` to `options`. + - delete `server`, `prerender`, and `ssr` from `options`. + - In `angular.json` under `/projects/angular-o1js-demo/architect/serve`, replace the default builder `"builder": "@angular-devkit/build-angular:dev-server",` with ` "builder": "@angular-builders/custom-webpack:dev-server". - The build targets should look like this: ```json @@ -294,18 +294,18 @@ npm i @angular-builders/custom-webpack ### Copy o1js into Static Assets -- Now we'll write a script to copy o1js into `public` where our static assets are served along with the application and then import it directly with an `importmap` +- Now we'll write a script to copy o1js into `public` where our static assets are served along with the application and then import it directly with an `importmap`. - Add a script to `package.json` that copies o1js from `node_modules` to a new directory at `public/lib/o1js`. - - Files under public are served with the app, so the file itself will be available at http://localhost:4200/lib/o1js/index.js + - Files under public are served with the app, so the file itself will be available at `http://localhost:4200/lib/o1js/index.js`. ```json "copy-libs": "mkdir -p public/lib/o1js && cp node_modules/o1js/dist/web/index.js public/lib/o1js/index.js" ``` -- add the `copy-o1js-lib` task to the build script and the start script - - `"build": "npm run copy-libs && ng build",` - - `"start": "npm run copy-libs && ng serve",` -- Add `public/lib` to `.gitignore` +- add the `copy-o1js-lib` task to the build script and the start script. + - `"build": "npm run copy-libs && ng build"` + - `"start": "npm run copy-libs && ng serve"` +- Add `public/lib` to `.gitignore`. ### Load o1js with an `importmap` @@ -351,7 +351,7 @@ const {Mina, PublicKey, fetchAccount} = o1js; - Now we'll set the app up for deployment to github pages. - Publish your project to a GitHub repository. -- Run `ng deploy` and select GitHub Pages +- Run `ng deploy` and select GitHub Pages. - Add `baseHref` to `options` under `build` in angular.json with the name of your github repository. - **Do not remove the slashes!** @@ -376,7 +376,7 @@ npm run deploy ## SharedArrayBuffer in Deployed Instance - View the site and open the browser console. You'll see the same error about the SharedArrayBuffer from before! The headers set previously apply only to `ng serve`, so we’ll set them up for GitHub Pages. -- Install `coi-serviceworker` +- Install `coi-serviceworker`. ```bash npm i coi-serviceworker @@ -388,8 +388,8 @@ npm i coi-serviceworker "copy-libs": "mkdir -p public/lib/o1js && cp node_modules/o1js/dist/web/index.js public/lib/o1js/index.js && cp node_modules/coi-serviceworker/coi-serviceworker.min.js public/lib/coi-serviceworker.min.js" ``` -- Create a file `src/app/COIServiceWorker.ts` with the following contents - - Be sure to replace \ with the name of your github repo! +- Create a file `src/app/COIServiceWorker.ts` with the following contents. + - Be sure to replace `` with the name of your github repo! ```tsx export {}; @@ -406,7 +406,7 @@ function loadCOIServiceWorker() { loadCOIServiceWorker(); ``` -- Import it at the top of `src/app/app.component.ts` +- Import it at the top of `src/app/app.component.ts`. ```tsx import './COIServiceWorker'; From da88022a3acfd3711b32ad6413d25ab389a16f23 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:48:00 +0800 Subject: [PATCH 3/7] fix broken minascan link --- docs/zkapps/front-end-integration-guides/angular.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index 34fc3548a..18d6e8b16 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -102,7 +102,7 @@ export class AppComponent { const {Mina, PublicKey, fetchAccount} = await import('o1js'); const {Add} = await import('../../../add'); // connect the Mina instance to testnet -Mina.setActiveInstance(Mina.Network('')); +Mina.setActiveInstance(Mina.Network('https://api.minascan.io/node/devnet/v1/graphql')); // we've already deployed the Add contract on testnet at this address // const zkAppAddress = `B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5`; From 9f60331964c4b7a28175257f5566992b94110fda Mon Sep 17 00:00:00 2001 From: hatty hattington <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:11:52 +0700 Subject: [PATCH 4/7] Update docs/zkapps/front-end-integration-guides/angular.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Boray Saygılıer --- docs/zkapps/front-end-integration-guides/angular.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index 18d6e8b16..5efb5445d 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -13,7 +13,7 @@ keywords: - Install a wallet that supports zkApp transactions. For this tutorial, we’ll use **Auro Wallet**. [Download it here](https://www.aurowallet.com/). - Add the Auro Wallet browser extension. - Open the extension and follow the steps to create a new wallet. -- Click **"Mainnet"** at the top of the extension view, then select **Show Testnet** from the menu. After that, select **Devnet**. +- Click **"Mainnet"** at the top of the extension view, then select **"Show Testnet"** from the menu. After that, select **"Devnet"**. - Using Devnet will allow us to interact with a test version of the Mina network without needing to spend real Mina to pay for transaction fees. - Fund your wallet using the [Mina Faucet](https://faucet.minaprotocol.com/). - You'll need to wait about 3 minutes to see the change in balance reflected on chain. You can use [Minascan](https://minascan.io/devnet) to track the status of your transaction. From f618e13dc69cb4f803c711c7cb8f6c2566f70f32 Mon Sep 17 00:00:00 2001 From: hatty hattington <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:12:05 +0700 Subject: [PATCH 5/7] Update docs/zkapps/front-end-integration-guides/angular.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Boray Saygılıer --- docs/zkapps/front-end-integration-guides/angular.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index 5efb5445d..ed644a896 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -16,7 +16,7 @@ keywords: - Click **"Mainnet"** at the top of the extension view, then select **"Show Testnet"** from the menu. After that, select **"Devnet"**. - Using Devnet will allow us to interact with a test version of the Mina network without needing to spend real Mina to pay for transaction fees. - Fund your wallet using the [Mina Faucet](https://faucet.minaprotocol.com/). - - You'll need to wait about 3 minutes to see the change in balance reflected on chain. You can use [Minascan](https://minascan.io/devnet) to track the status of your transaction. + - You'll need to wait one block (~3 minutes) to see the change in balance reflected on chain. You can use [Minascan](https://minascan.io/devnet) to track the status of your transaction. ## Initialize the Project From 116887dca7c9ccda3954192c072c3d82449769fb Mon Sep 17 00:00:00 2001 From: hatty hattington <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 1 Dec 2024 21:12:41 +0700 Subject: [PATCH 6/7] Update docs/zkapps/front-end-integration-guides/angular.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Boray Saygılıer --- docs/zkapps/front-end-integration-guides/angular.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index ed644a896..cb7c92df7 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -219,7 +219,7 @@ npm i @angular-builders/custom-webpack - rename the browser property to `main` in `options`. - add `"customWebpackConfig": { "path": "./webpack.config.js" },` to `options`. - delete `server`, `prerender`, and `ssr` from `options`. - - In `angular.json` under `/projects/angular-o1js-demo/architect/serve`, replace the default builder `"builder": "@angular-devkit/build-angular:dev-server",` with ` "builder": "@angular-builders/custom-webpack:dev-server". + - In `angular.json` under `/projects/angular-o1js-demo/architect/serve`, replace the default builder `"builder": "@angular-devkit/build-angular:dev-server",` with `"builder": "@angular-builders/custom-webpack:dev-server"`. - The build targets should look like this: ```json From e7245b70ad9f4409e85a95fbb7585b4f5157fce0 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 1 Dec 2024 19:37:45 -0700 Subject: [PATCH 7/7] fix inconsistencies in capitalization --- .../front-end-integration-guides/angular.mdx | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/docs/zkapps/front-end-integration-guides/angular.mdx b/docs/zkapps/front-end-integration-guides/angular.mdx index 18d6e8b16..7f430fe64 100644 --- a/docs/zkapps/front-end-integration-guides/angular.mdx +++ b/docs/zkapps/front-end-integration-guides/angular.mdx @@ -1,5 +1,5 @@ --- -title: Angular and Github Pages +title: Angular and GitHub Pages description: Getting started with Angular keywords: - angular @@ -20,7 +20,7 @@ keywords: ## Initialize the Project -- Install the Angular cli globally: +- Install the Angular CLI globally: ```bash npm install -g @angular/cli @@ -32,7 +32,7 @@ npm install -g @angular/cli ng new ``` -- Install the Angular cli `npm install -g @angular/cli` +- Install the Angular CLI `npm install -g @angular/cli` - Create a new project `ng new ` - Select your preferred stylesheet format. - For **Server-Side Rendering (SSR)** and **Static Site Generation (SSG/Prerendering)**, choose **Yes**. @@ -59,7 +59,7 @@ cd ../ npm install -g zkapp-cli ``` -- Initialize a new zkapp with the cli. When prompted to create a UI project, select **none**. +- Initialize a new zkapp with the CLI. When prompted to create a UI project, select **none**. ```bash zk project add @@ -77,7 +77,7 @@ npm run build ## Call Contracts -- Move back into the angular project. +- Move back into the Angular project. - To interact with the deployed `Add` contract, we’ll add code to fetch the current state and initiate a transaction. This code will execute only in the browser, so we'll add it to `afterNextRender` in the constructor of `src/app/app.component.ts`. - `afterNextRender` only runs after the Angular component has fully rendered. - The Auro wallet injects a Mina provider into the global context. It is accessible as `window.mina`. @@ -102,17 +102,17 @@ export class AppComponent { const {Mina, PublicKey, fetchAccount} = await import('o1js'); const {Add} = await import('../../../add'); // connect the Mina instance to testnet -Mina.setActiveInstance(Mina.Network('https://api.minascan.io/node/devnet/v1/graphql')); + Mina.setActiveInstance(Mina.Network('https://api.minascan.io/node/devnet/v1/graphql')); // we've already deployed the Add contract on testnet at this address - // -const zkAppAddress = `B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5`; + // https://minascan.io/devnet/account/B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5 + const zkAppAddress = `B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5`; await fetchAccount({publicKey: zkAppAddress}); const zkApp = new Add(PublicKey.fromBase58(zkAppAddress)); // Read state from the testnet Add contract -console.log(`Reading state of add contract at ${zkAppAddress}: num=${zkApp.num.get()}`); + console.log(`Reading state of add contract at ${zkAppAddress}: num=${zkApp.num.get()}`); try { // retrieve the injected mina provider if it exists -const mina = (window as any).mina; + const mina = (window as any).mina; const walletKey: string = (await mina.requestAccounts())[0]; console.log(`Injected mina provider address: ${walletKey}`); await fetchAccount({publicKey: PublicKey.fromBase58(walletKey)}); @@ -121,32 +121,27 @@ const mina = (window as any).mina; console.log("Compiled Add"); // send a transaction with the injected Mina provider -const transaction = await Mina.transaction(async () => { + const transaction = await Mina.transaction(async () => { await zkApp.update(); }); await transaction.prove(); - const {hash} = await (window as any).mina.sendTransaction({ + const {hash} = await mina.sendTransaction({ transaction: transaction.toJSON(), }); // display the link to the transaction -const transactionLink = `https://minascan.io/devnet/tx/${hash}`; - console.log(`View transaction at ${transactionLink}`); - } catch (e: any) { + const transactionLink = `https://minascan.io/devnet/tx/${hash}`; + console.log(`View transaction at ${transactionLink}`); + } catch (e: any) { console.error(e.message); - - switch (e.message) { - case e.message.includes("Cannot read properties of undefined (reading 'requestAccounts')"): - console.error("Is Auro installed?"); - break; - case e.message.includes("Please create or restore wallet first."): - console.error("Have you created a wallet?"); - break; - case e.message.includes("User rejected the request."): - console.error("Did you grant the app permission to connect to your wallet?"); - break; - default: - console.error("An unknown error occurred:", e); + if (e.message.includes("Cannot read properties of undefined (reading 'requestAccounts')")) { + console.error("Is Auro installed?"); + } else if (e.message.includes("Please create or restore wallet first.")) { + console.error("Have you created a wallet?"); + } else if (e.message.includes("User rejected the request.")) { + console.error("Did you grant the app permission to connect to your wallet?"); + } else { + console.error("An unknown error occurred:", e); } } }); @@ -173,7 +168,7 @@ const transactionLink = `https://minascan.io/devnet/tx/${hash}`; - Cross-Origin-Opener-Policy (COOP) must be set to `"same-origin"` to prevents cross-origin resources from accessing the main document’s memory. - Cross-Origin-Embedder-Policy (COEP) must be set to `"require-corp"` to restrict the way cross origin resources can be loaded by the main document. They'll either need to be from the same origin or include the `Cross-Origin-Resource-Policy: cross-origin` header. - Depending on how the application is being run, there are different ways to set these headers. Running the application locally with `ng serve` uses `@angular-devkit/build-angular:dev-server"` which we can configure in the project's `angular.json` file at `/projects/angular-o1js-demo/architect/serve/configurations/development`. -- Architect is angular's task runner, the entries (called build targets) under `architect` each represent tasks that the angular cli can run (`ng build`, `ng serve`, `ng test`, etc). The `builder` property of each target specifies the program that Architect should run to execute the task. The `options` can be used to supply parameters to the builder, and the `configurations`specifies a custom set of options for different target configurations (development, production, etc). +- Architect is Angular's task runner, the entries (called build targets) under `architect` each represent tasks that the Angular CLI can run (`ng build`, `ng serve`, `ng test`, etc). The `builder` property of each target specifies the program that Architect should run to execute the task. The `options` can be used to supply parameters to the builder, and the `configurations`specifies a custom set of options for different target configurations (development, production, etc). - Running `ng serve` locally runs the `@angular-devkit/build-angular:dev-server` builder, and in its options object we can specify custom headers specifying the headers required for `SharedArrayBuffer` as follows: ``` @@ -302,7 +297,7 @@ npm i @angular-builders/custom-webpack "copy-libs": "mkdir -p public/lib/o1js && cp node_modules/o1js/dist/web/index.js public/lib/o1js/index.js" ``` -- add the `copy-o1js-lib` task to the build script and the start script. +- Add the `copy-o1js-lib` task to the build script and the start script. - `"build": "npm run copy-libs && ng build"` - `"start": "npm run copy-libs && ng serve"` - Add `public/lib` to `.gitignore`. @@ -347,12 +342,12 @@ const {Mina, PublicKey, fetchAccount} = o1js; - Verify that "Compiled Add" is logged, meaning that the SDK has successfully generated a proving key for the `Add` zkapp. - If you're connected to Devnet and your account is funded with Devnet tokens, you should be be able to broadcast a successful transaction calling `update` on the zkapp. After a few minutes, the state change associated with the transaction will take effect on chain and you'll see `num` increase when you reload the page! -## Deploying to Github Pages +## Deploying to GitHub Pages -- Now we'll set the app up for deployment to github pages. +- Now we'll set the app up for deployment to GitHub pages. - Publish your project to a GitHub repository. - Run `ng deploy` and select GitHub Pages. -- Add `baseHref` to `options` under `build` in angular.json with the name of your github repository. +- Add `baseHref` to `options` under `build` in angular.json with the name of your GitHub repository. - **Do not remove the slashes!** ```json @@ -389,7 +384,7 @@ npm i coi-serviceworker ``` - Create a file `src/app/COIServiceWorker.ts` with the following contents. - - Be sure to replace `` with the name of your github repo! + - Be sure to replace `` with the name of your GitHub repo! ```tsx export {};