From 955697d230d10fc7565bde6ec33841b9bf30277a Mon Sep 17 00:00:00 2001 From: Brent C Date: Wed, 2 Aug 2023 16:03:11 -0400 Subject: [PATCH] [Fix] Improved loading (#700) * initial loading test * loading animations, not working aleo wasm * working webassembly init * removing comments * removing console log * Update website/src/workers/worker.js Co-authored-by: Mike Turner Signed-off-by: Brent C --------- Signed-off-by: Brent C Co-authored-by: Mike Turner --- website/index.html | 60 ++++++++++++++++++++- website/src/aleo-wasm-hook.js | 10 ++-- website/src/index.jsx | 5 +- website/src/tabs/develop/Deploy.jsx | 9 ++-- website/src/tabs/develop/ExecuteLegacy.jsx | 5 +- website/src/utils.js | 38 ------------- website/src/workers/WorkerContext.js | 5 ++ website/src/workers/WorkerProvider.jsx | 42 +++++++++++++++ website/src/workers/worker.js | 62 ++++++++++++++++++---- 9 files changed, 175 insertions(+), 61 deletions(-) delete mode 100644 website/src/utils.js create mode 100644 website/src/workers/WorkerContext.js create mode 100644 website/src/workers/WorkerProvider.jsx diff --git a/website/index.html b/website/index.html index 3425a982a..ff1da19c9 100644 --- a/website/index.html +++ b/website/index.html @@ -12,10 +12,68 @@ Aleo SDK + -
+
+
+
+
+
+
diff --git a/website/src/aleo-wasm-hook.js b/website/src/aleo-wasm-hook.js index 43b8c4fca..02a9028bd 100644 --- a/website/src/aleo-wasm-hook.js +++ b/website/src/aleo-wasm-hook.js @@ -1,12 +1,14 @@ import { useEffect, useState } from "react"; +import init, * as aleo from "@aleohq/wasm"; +await init(); export const useAleoWASM = () => { - const [aleo, setAleo] = useState(null); + const [aleoInstance, setAleoInstance] = useState(null); useEffect(() => { - if (aleo === null) { - import("@aleohq/wasm").then((module) => setAleo(module)); + if (aleoInstance === null) { + setAleoInstance(aleo); } }, []); // eslint-disable-line react-hooks/exhaustive-deps - return aleo; + return aleoInstance; }; diff --git a/website/src/index.jsx b/website/src/index.jsx index 8219f17a4..89e72b3dc 100644 --- a/website/src/index.jsx +++ b/website/src/index.jsx @@ -3,12 +3,15 @@ import "./index.css"; import { createRoot } from "react-dom/client"; import { RouterProvider } from "react-router-dom"; import { router } from "./routing.jsx"; +import WorkerProvider from "./workers/WorkerProvider.jsx"; const container = document.getElementById("root"); const root = createRoot(container); root.render( - + + + , ); diff --git a/website/src/tabs/develop/Deploy.jsx b/website/src/tabs/develop/Deploy.jsx index 69e04677e..080cc7978 100644 --- a/website/src/tabs/develop/Deploy.jsx +++ b/website/src/tabs/develop/Deploy.jsx @@ -10,12 +10,9 @@ import { Row, Result, Spin, - Space + Space, } from "antd"; import axios from "axios"; -import init, * as aleo from "@aleohq/wasm"; - -await init(); export const Deploy = () => { const [deploymentFeeRecord, setDeploymentFeeRecord] = useState(null); @@ -132,7 +129,9 @@ export const Deploy = () => { setLoading(false); setTransactionID(null); setDeploymentError(null); - messageApi.info("Disclaimer: Fee estimation is experimental and may not represent a correct estimate on any current or future network"); + messageApi.info( + "Disclaimer: Fee estimation is experimental and may not represent a correct estimate on any current or future network", + ); await postMessagePromise(worker, { type: "ALEO_ESTIMATE_DEPLOYMENT_FEE", program: programString(), diff --git a/website/src/tabs/develop/ExecuteLegacy.jsx b/website/src/tabs/develop/ExecuteLegacy.jsx index 9f0ac7e3e..ec99cf5d4 100644 --- a/website/src/tabs/develop/ExecuteLegacy.jsx +++ b/website/src/tabs/develop/ExecuteLegacy.jsx @@ -15,9 +15,7 @@ import { } from "antd"; import { FormGenerator } from "../../components/InputForm"; import axios from "axios"; -import init, * as aleo from "@aleohq/wasm"; - -await init(); +import { useAleoWASM } from "../../aleo-wasm-hook"; export const ExecuteLegacy = () => { const [executionFeeRecord, setExecutionFeeRecord] = useState(null); @@ -39,6 +37,7 @@ export const ExecuteLegacy = () => { const [executeOnline, setExecuteOnline] = useState(false); const [programInputs, setProgramInputs] = useState(null); const [tip, setTip] = useState("Executing Program..."); + const aleo = useAleoWASM(); const getProgramInputs = () => { const programManifest = []; diff --git a/website/src/utils.js b/website/src/utils.js deleted file mode 100644 index 3eaae3453..000000000 --- a/website/src/utils.js +++ /dev/null @@ -1,38 +0,0 @@ -import init, * as aleo from "@aleohq/wasm"; - -await init(); - -// Get program source code from the Aleo network -async function getProgram(name) { - const response = await fetch(`https://vm.aleo.org/api/testnet3/program/${name}`); - if (response.ok) { - return response.json(); - } - throw new Error("Unable to get program"); -} - -// Recursively resolve imports for programs and return a map of program_id to program -// in the form of { "program name": "program source code" }. The object returned from -// this function should be passed to the "imports" parameter of the aleo-wasm program -// execution and deployment functions. -async function resolveImports(program_code) { - let program = aleo.Program.fromString(program_code); - const imports = {}; - let importList = program.getImports(); - for (let i = 0; i < importList.length; i++) { - const import_id = importList[i]; - if (!imports[import_id]) { - const importedProgram = await getProgram(import_id); - const nestedImports = await resolveImports(importedProgram); - for (const key in nestedImports) { - if (!imports[key]) { - imports[key] = nestedImports[key]; - } - } - imports[import_id] = importedProgram; - } - } - return imports; -} - -export { getProgram, resolveImports }; \ No newline at end of file diff --git a/website/src/workers/WorkerContext.js b/website/src/workers/WorkerContext.js new file mode 100644 index 000000000..78df7dfd7 --- /dev/null +++ b/website/src/workers/WorkerContext.js @@ -0,0 +1,5 @@ +import React from "react"; + +const WorkerContext = React.createContext(null); + +export default WorkerContext; diff --git a/website/src/workers/WorkerProvider.jsx b/website/src/workers/WorkerProvider.jsx new file mode 100644 index 000000000..0cbdee49b --- /dev/null +++ b/website/src/workers/WorkerProvider.jsx @@ -0,0 +1,42 @@ +import { useEffect, useState } from "react"; +import WorkerContext from "./WorkerContext"; + +const WorkerProvider = ({ children }) => { + const [worker, setWorker] = useState(null); + const [workerReady, setWorkerReady] = useState(false); + + useEffect(() => { + let worker = new Worker(new URL("./worker.js", import.meta.url), { + type: "module", + }); + setWorker(worker); + + worker.onmessage = (event) => { + if (event.data.type === "ALEO_WORKER_READY") { + setWorkerReady(true); + } + }; + + return () => { + worker.terminate(); + }; + }, []); + + if (!workerReady) { + return ( + <> +
+
+
+ + ); + } + + return ( + + {children} + + ); +}; + +export default WorkerProvider; diff --git a/website/src/workers/worker.js b/website/src/workers/worker.js index ace7984fd..05007b1d5 100644 --- a/website/src/workers/worker.js +++ b/website/src/workers/worker.js @@ -1,5 +1,4 @@ import init, * as aleo from "@aleohq/wasm"; -import { resolveImports } from "../utils.js"; import { FEE_PROVER_URL, FEE_VERIFIER_URL, @@ -36,6 +35,10 @@ await init(); await aleo.initThreadPool(10); const aleoProgramManager = new aleo.ProgramManager(); +self.postMessage({ + type: "ALEO_WORKER_READY", +}); + const getFunctionKeys = async (proverUrl, verifierUrl) => { console.log( "Downloading proving and verifying keys from: ", @@ -113,7 +116,7 @@ self.addEventListener("message", (ev) => { aleoFunction, inputs, true, - imports + imports, ); console.log( @@ -123,10 +126,16 @@ self.addEventListener("message", (ev) => { ); let outputs = response.getOutputs(); console.log(`Function execution response: ${outputs}`); - self.postMessage({ type: "OFFLINE_EXECUTION_COMPLETED", outputs }); + self.postMessage({ + type: "OFFLINE_EXECUTION_COMPLETED", + outputs, + }); } catch (error) { console.log(error); - self.postMessage({ type: "ERROR", errorMessage: error.toString() }); + self.postMessage({ + type: "ERROR", + errorMessage: error.toString(), + }); } })(); } else if (ev.data.type === "ALEO_EXECUTE_PROGRAM_ON_CHAIN") { @@ -179,7 +188,7 @@ self.addEventListener("message", (ev) => { aleo.RecordPlaintext.fromString(feeRecord), url, true, - imports + imports, ); console.log( @@ -274,7 +283,7 @@ self.addEventListener("message", (ev) => { await aleoProgramManager.estimateDeploymentFee( program, false, - imports + imports, ); console.log( @@ -307,7 +316,9 @@ self.addEventListener("message", (ev) => { url, } = ev.data; - console.log(`Web worker: Creating transfer of type ${transfer_type}...`); + console.log( + `Web worker: Creating transfer of type ${transfer_type}...`, + ); let startTime = performance.now(); (async function () { @@ -434,7 +445,10 @@ self.addEventListener("message", (ev) => { ); } - let transferAmountRecord = amountRecord !== undefined ? aleo.RecordPlaintext.fromString(amountRecord) : undefined; + let transferAmountRecord = + amountRecord !== undefined + ? aleo.RecordPlaintext.fromString(amountRecord) + : undefined; let transferTransaction = await aleoProgramManager.transfer( aleo.PrivateKey.from_string(privateKey), @@ -512,7 +526,7 @@ self.addEventListener("message", (ev) => { aleo.RecordPlaintext.fromString(feeRecord), url, true, - imports + imports, ); console.log( @@ -656,3 +670,33 @@ self.addEventListener("message", (ev) => { })(); } }); + +async function resolveImports(program_code) { + let program = aleo.Program.fromString(program_code); + const imports = {}; + let importList = program.getImports(); + for (let i = 0; i < importList.length; i++) { + const import_id = importList[i]; + if (!imports[import_id]) { + const importedProgram = await getProgram(import_id); + const nestedImports = await resolveImports(importedProgram); + for (const key in nestedImports) { + if (!imports[key]) { + imports[key] = nestedImports[key]; + } + } + imports[import_id] = importedProgram; + } + } + return imports; +} + +async function getProgram(name) { + const response = await fetch( + `https://vm.aleo.org/api/testnet3/program/${name}`, + ); + if (response.ok) { + return response.json(); + } + throw new Error("Unable to get program"); +}