From fd267c6788901efbf94f35d7ee87ad38615d45ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Utku=20Y=C4=B1ld=C4=B1z?= Date: Tue, 23 Apr 2024 19:47:36 +0300 Subject: [PATCH 1/2] Updated template for next.js --- create-aleo-app/template-nextjs-ts/.gitignore | 35 ++++++++ .../helloworld/.env.example | 2 + .../template-nextjs-ts/helloworld/README.md | 13 +++ .../helloworld/build/main.aleo | 7 ++ .../helloworld/build/program.json | 6 ++ .../helloworld/inputs/helloworld.in | 4 + .../helloworld/program.json | 6 ++ .../helloworld/src/main.leo | 7 ++ .../template-nextjs-ts/next.config.js | 41 +++++++-- .../template-nextjs-ts/package.json | 9 +- .../template-nextjs-ts/src/app/custom.d.ts | 16 ++++ .../template-nextjs-ts/src/app/page.tsx | 88 +++++++------------ .../template-nextjs-ts/src/app/worker.ts | 47 ---------- .../src/app/workers/AleoWorker.ts | 18 ++++ .../src/app/workers/worker.ts | 66 ++++++++++++++ .../template-nextjs-ts/tsconfig.json | 2 +- 16 files changed, 250 insertions(+), 117 deletions(-) create mode 100644 create-aleo-app/template-nextjs-ts/.gitignore create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/.env.example create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/README.md create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/build/main.aleo create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/build/program.json create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/inputs/helloworld.in create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/program.json create mode 100644 create-aleo-app/template-nextjs-ts/helloworld/src/main.leo create mode 100644 create-aleo-app/template-nextjs-ts/src/app/custom.d.ts delete mode 100644 create-aleo-app/template-nextjs-ts/src/app/worker.ts create mode 100644 create-aleo-app/template-nextjs-ts/src/app/workers/AleoWorker.ts create mode 100644 create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts diff --git a/create-aleo-app/template-nextjs-ts/.gitignore b/create-aleo-app/template-nextjs-ts/.gitignore new file mode 100644 index 000000000..8f322f0d8 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/create-aleo-app/template-nextjs-ts/helloworld/.env.example b/create-aleo-app/template-nextjs-ts/helloworld/.env.example new file mode 100644 index 000000000..11b672e98 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/.env.example @@ -0,0 +1,2 @@ +NETWORK=testnet3 +PRIVATE_KEY=user1PrivateKey \ No newline at end of file diff --git a/create-aleo-app/template-nextjs-ts/helloworld/README.md b/create-aleo-app/template-nextjs-ts/helloworld/README.md new file mode 100644 index 000000000..2456ef654 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/README.md @@ -0,0 +1,13 @@ +# helloworld.aleo + +## Build Guide + +To compile this Aleo program, run: +```bash +snarkvm build +``` + +To execute this Aleo program, run: +```bash +snarkvm run hello +``` diff --git a/create-aleo-app/template-nextjs-ts/helloworld/build/main.aleo b/create-aleo-app/template-nextjs-ts/helloworld/build/main.aleo new file mode 100644 index 000000000..94ff0de38 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/build/main.aleo @@ -0,0 +1,7 @@ +program helloworld_next1.aleo; + +function main: + input r0 as u32.public; + input r1 as u32.private; + add r0 r1 into r2; + output r2 as u32.private; diff --git a/create-aleo-app/template-nextjs-ts/helloworld/build/program.json b/create-aleo-app/template-nextjs-ts/helloworld/build/program.json new file mode 100644 index 000000000..c478377b1 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/build/program.json @@ -0,0 +1,6 @@ +{ + "program": "helloworld_next1.aleo", + "version": "0.0.0", + "description": "", + "license": "MIT" +} diff --git a/create-aleo-app/template-nextjs-ts/helloworld/inputs/helloworld.in b/create-aleo-app/template-nextjs-ts/helloworld/inputs/helloworld.in new file mode 100644 index 000000000..2908f3dee --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/inputs/helloworld.in @@ -0,0 +1,4 @@ +// The program input for helloworld/src/main.leo +[main] +public a: u32 = 1u32; +b: u32 = 2u32; diff --git a/create-aleo-app/template-nextjs-ts/helloworld/program.json b/create-aleo-app/template-nextjs-ts/helloworld/program.json new file mode 100644 index 000000000..df13181a2 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/program.json @@ -0,0 +1,6 @@ +{ + "program": "helloworld.aleo", + "version": "0.0.0", + "description": "", + "license": "MIT" +} diff --git a/create-aleo-app/template-nextjs-ts/helloworld/src/main.leo b/create-aleo-app/template-nextjs-ts/helloworld/src/main.leo new file mode 100644 index 000000000..9aa61dacf --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/helloworld/src/main.leo @@ -0,0 +1,7 @@ +// The 'helloworld' program. +program helloworld.aleo { + transition main(public a: u32, b: u32) -> u32 { + let c: u32 = a + b; + return c; + } +} diff --git a/create-aleo-app/template-nextjs-ts/next.config.js b/create-aleo-app/template-nextjs-ts/next.config.js index 9568d4014..d3e79ec20 100644 --- a/create-aleo-app/template-nextjs-ts/next.config.js +++ b/create-aleo-app/template-nextjs-ts/next.config.js @@ -1,5 +1,5 @@ -const TerserPlugin = require("terser-webpack-plugin") -/** @type {import('next').NextConfig} */ +const TerserPlugin = require("terser-webpack-plugin"); + const nextConfig = { async headers() { return [ @@ -18,15 +18,38 @@ const nextConfig = { }, ] }, - webpack: (config) => { + webpack: (config, { isServer }) => { + + config.module.rules.push({ + test: /\.aleo$/, + use: 'raw-loader', + }); + + if (!isServer) { + config.resolve.fallback = { + fs: false, + net: false, + tls: false, + }; + } + + config.experiments = { ...config.experiments, topLevelAwait: true }; - config.optimization = { ...config.optimization, minimize: true, minimizer: [new TerserPlugin({ - terserOptions: { - module: true, - } - })], } + config.optimization = { + ...config.optimization, + minimize: true, + runtimeChunk: 'single', + minimizer: [ + new TerserPlugin({ + terserOptions: { + module: true, + } + }), + ] + }; + return config; }, } -module.exports = nextConfig +module.exports = nextConfig; diff --git a/create-aleo-app/template-nextjs-ts/package.json b/create-aleo-app/template-nextjs-ts/package.json index 9d128c863..e1828053e 100644 --- a/create-aleo-app/template-nextjs-ts/package.json +++ b/create-aleo-app/template-nextjs-ts/package.json @@ -1,5 +1,5 @@ { - "name": "template-nextjs", + "name": "test-next", "version": "0.1.0", "private": true, "scripts": { @@ -10,15 +10,18 @@ }, "dependencies": { "@aleohq/sdk": "^0.6.2", + "circular-dependency-plugin": "^5.2.2", + "comlink": "^4.4.1", "next": "13.5.4", "react": "^18", - "react-dom": "^18", - "terser-webpack-plugin": "^5.3.9" + "react-dom": "^18" }, "devDependencies": { "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "raw-loader": "^4.0.2", + "terser-webpack-plugin": "^5.3.10", "typescript": "^5" } } diff --git a/create-aleo-app/template-nextjs-ts/src/app/custom.d.ts b/create-aleo-app/template-nextjs-ts/src/app/custom.d.ts new file mode 100644 index 000000000..3aa72e286 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/src/app/custom.d.ts @@ -0,0 +1,16 @@ +declare module '*.svg' { + const content: any; + export default content; + } + + declare module '*.aleo' { + const content: string; + export default content; + } + + declare module '*?raw' { + const content: string; + export default content; + } + + \ No newline at end of file diff --git a/create-aleo-app/template-nextjs-ts/src/app/page.tsx b/create-aleo-app/template-nextjs-ts/src/app/page.tsx index 4ac0104a5..d6b99652b 100644 --- a/create-aleo-app/template-nextjs-ts/src/app/page.tsx +++ b/create-aleo-app/template-nextjs-ts/src/app/page.tsx @@ -3,89 +3,63 @@ import Image from "next/image"; import styles from "./page.module.css"; import { useCallback, useEffect, useRef, useState } from "react"; +import { AleoWorker } from './workers/AleoWorker'; +import program_data from "../../helloworld/build/main.aleo?raw"; +const aleoWorker = AleoWorker(); export default function Home() { const [account, setAccount] = useState(null); const [executing, setExecuting] = useState(false); const generateAccount = async () => { - workerRef.current?.postMessage("key"); + const key = await aleoWorker.getPrivateKey(); + setAccount(key); }; - async function execute() { + const execute = async () => { setExecuting(true); - workerRef.current?.postMessage("execute"); - } - - const workerRef = useRef(); - - interface AleoWorkerMessageEvent { - type: string; - result: any; - } - - useEffect(() => { - workerRef.current = new Worker(new URL("worker.ts", import.meta.url)); - workerRef.current.onmessage = ( - event: MessageEvent - ) => { - if (event.data.type === "key") { - setAccount(event.data.result); - } else if (event.data.type === "execute") { - setExecuting(false); - } - alert(`WebWorker Response => ${event.data.result}`); - }; - return () => { - workerRef.current?.terminate(); - }; - }, []); + const result = await aleoWorker.localProgramExecution( + program_data, + "main", + ["3u32", "5u32"], + ); + setExecuting(false); + alert(`Execution Result: ${result}`); + }; - const handleWork = useCallback(async () => { - workerRef.current?.postMessage("execute"); - }, []); + + const deploy = async () => { + setExecuting(true); + const deploymentResult = await aleoWorker.deployProgram(program_data); + setExecuting(false); + alert(`Deployment Result: ${deploymentResult}`); + }; return (
-

- Get started by editing  - src/app/page.tsx -

+

Get started by editing src/app/page.tsx

- Next.js Logo - Next.js Logo + Next.js Logo + Aleo Logo

+

+

+

diff --git a/create-aleo-app/template-nextjs-ts/src/app/worker.ts b/create-aleo-app/template-nextjs-ts/src/app/worker.ts deleted file mode 100644 index a18671384..000000000 --- a/create-aleo-app/template-nextjs-ts/src/app/worker.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - Account, - initThreadPool, - PrivateKey, - ProgramManager, -} from "@aleohq/sdk"; - -await initThreadPool(); - -const hello_hello_program =` -program hello_hello.aleo; - -function hello: - input r0 as u32.public; - input r1 as u32.private; - add r0 r1 into r2; - output r2 as u32.private;` - -async function localProgramExecution(program: string, aleoFunction: string, inputs: string[]) { - const programManager = new ProgramManager(); - - // Create a temporary account for the execution of the program - const account = new Account(); - programManager.setAccount(account); - - const executionResponse = await programManager.run( - program, - aleoFunction, - inputs, - false, - ); - return executionResponse.getOutputs(); -} - -function getPrivateKey() { - return new PrivateKey().to_string(); -} - -onmessage = async function (e) { - if (e.data === "execute") { - const result = await localProgramExecution(hello_hello_program, "hello", ["5u32", "5u32"]); - postMessage({type: "execute", result: result}); - } else if (e.data === "key") { - const result = getPrivateKey(); - postMessage({type: "key", result: result}); - } -}; diff --git a/create-aleo-app/template-nextjs-ts/src/app/workers/AleoWorker.ts b/create-aleo-app/template-nextjs-ts/src/app/workers/AleoWorker.ts new file mode 100644 index 000000000..edc1e04d7 --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/src/app/workers/AleoWorker.ts @@ -0,0 +1,18 @@ +import { wrap } from "comlink"; + +let singletonWorker:any = null; + +const AleoWorker = () => { + if (!singletonWorker && typeof window !== "undefined") { + const worker = new Worker(new URL("worker", import.meta.url), { + type: "module", + }); + worker.onerror = function(event) { + console.error("Error in worker:", event.message); + }; + singletonWorker = wrap(worker); + } + return singletonWorker; +}; + +export { AleoWorker }; diff --git a/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts b/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts new file mode 100644 index 000000000..f00cdf8fd --- /dev/null +++ b/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts @@ -0,0 +1,66 @@ +import { + Account, + ProgramManager, + PrivateKey, + initThreadPool, + AleoKeyProvider, + AleoNetworkClient, + NetworkRecordProvider, +} from "@aleohq/sdk"; +import { expose } from 'comlink'; + +await initThreadPool(); + +async function localProgramExecution(program:string, aleoFunction:string, inputs:any) { + const programManager = new ProgramManager(); + + // Create a temporary account for the execution of the program + const account = new Account(); + programManager.setAccount(account); + + const executionResponse = await programManager.run( + program, + aleoFunction, + inputs, + false, + ); + return executionResponse.getOutputs(); +} + +function getPrivateKey() { + const key = new PrivateKey(); + return key.to_string(); +} + +async function deployProgram(program : string) { + const keyProvider = new AleoKeyProvider(); + keyProvider.useCache(true); + + const networkClient = new AleoNetworkClient("https://api.explorer.aleo.org/v1"); + + const account = new Account({ + privateKey: "APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx", + }); + + const recordProvider = new NetworkRecordProvider(account, networkClient); + + const programManager = new ProgramManager( + "https://api.explorer.aleo.org/v1", + keyProvider, + recordProvider, + ); + + programManager.setAccount(account); + const fee = 1.9; // 1.9 Aleo credits + + const tx_id = await programManager.deploy(program, fee, false); + return tx_id; +} + +const api = { + localProgramExecution, + getPrivateKey, + deployProgram +}; + +expose(api); diff --git a/create-aleo-app/template-nextjs-ts/tsconfig.json b/create-aleo-app/template-nextjs-ts/tsconfig.json index 54698a489..7190f7b71 100644 --- a/create-aleo-app/template-nextjs-ts/tsconfig.json +++ b/create-aleo-app/template-nextjs-ts/tsconfig.json @@ -22,6 +22,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/custom.d.ts"], "exclude": ["node_modules"] } From 765304d9017831703b9374ebb9fdeb398c4b6d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20Utku=20Y=C4=B1ld=C4=B1z?= Date: Tue, 23 Apr 2024 19:51:41 +0300 Subject: [PATCH 2/2] PKey update --- create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts b/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts index f00cdf8fd..5840b788a 100644 --- a/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts +++ b/create-aleo-app/template-nextjs-ts/src/app/workers/worker.ts @@ -39,7 +39,7 @@ async function deployProgram(program : string) { const networkClient = new AleoNetworkClient("https://api.explorer.aleo.org/v1"); const account = new Account({ - privateKey: "APrivateKey1zkpBvXdKZKaXXcLUnwAVFCQNp41jrX6JqTuJo1JShfPoRfx", + privateKey: "userPrivateKey", }); const recordProvider = new NetworkRecordProvider(account, networkClient);