diff --git a/apps/aztec-compiler/.eslintrc b/apps/aztec-compiler/.eslintrc
new file mode 100644
index 00000000000..2d85f9fa667
--- /dev/null
+++ b/apps/aztec-compiler/.eslintrc
@@ -0,0 +1,3 @@
+{
+ "extends": "../../.eslintrc.json",
+}
\ No newline at end of file
diff --git a/apps/aztec-compiler/project.json b/apps/aztec-compiler/project.json
new file mode 100644
index 00000000000..a07642b07ba
--- /dev/null
+++ b/apps/aztec-compiler/project.json
@@ -0,0 +1,67 @@
+{
+ "name": "aztec-compiler",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/aztec-compiler/src",
+ "projectType": "application",
+ "implicitDependencies": [],
+ "targets": {
+ "build": {
+ "executor": "@nrwl/webpack:webpack",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "development",
+ "options": {
+ "compiler": "babel",
+ "outputPath": "dist/apps/aztec-compiler",
+ "index": "apps/aztec-compiler/src/index.html",
+ "baseHref": "./",
+ "main": "apps/aztec-compiler/src/main.tsx",
+ "polyfills": "apps/aztec-compiler/src/polyfills.ts",
+ "tsConfig": "apps/aztec-compiler/tsconfig.app.json",
+ "assets": ["apps/aztec-compiler/src/profile.json"],
+ "styles": ["apps/aztec-compiler/src/css/app.css"],
+ "scripts": [],
+ "webpackConfig": "apps/aztec-compiler/webpack.config.js"
+ },
+ "configurations": {
+ "development": {
+ },
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "apps/aztec-compiler/src/environments/environment.ts",
+ "with": "apps/aztec-compiler/src/environments/environment.prod.ts"
+ }
+ ]
+ }
+ }
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/aztec-compiler/**/*.ts"],
+ "eslintConfig": "apps/aztec-compiler/.eslintrc"
+ }
+ },
+ "serve": {
+ "executor": "@nrwl/webpack:dev-server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "aztec-compiler:build",
+ "hmr": true,
+ "baseHref": "/"
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "aztec-compiler:build:development",
+ "port": 2023
+ },
+ "production": {
+ "buildTarget": "aztec-compiler:build:production"
+ }
+ }
+ }
+ },
+ "tags": []
+ }
+
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/app/app.tsx b/apps/aztec-compiler/src/app/app.tsx
new file mode 100644
index 00000000000..e51a0a6b1d5
--- /dev/null
+++ b/apps/aztec-compiler/src/app/app.tsx
@@ -0,0 +1,27 @@
+import { useReducer } from 'react'
+import { IntlProvider } from 'react-intl'
+import { RenderIf } from '@remix-ui/helper'
+import { Compile } from './components/Compile'
+import { pluginReducer, initialState } from './reducers/state'
+import { AztecPluginClient } from './services/aztecPluginClient'
+import { PluginContext } from './contexts/pluginContext'
+
+const plugin = new AztecPluginClient()
+
+function App() {
+ const [state, dispatch] = useReducer(pluginReducer, initialState)
+
+ return (
+
+ )
+}
+
+export default App
diff --git a/apps/aztec-compiler/src/app/components/Compile.tsx b/apps/aztec-compiler/src/app/components/Compile.tsx
new file mode 100644
index 00000000000..508331fb7db
--- /dev/null
+++ b/apps/aztec-compiler/src/app/components/Compile.tsx
@@ -0,0 +1,310 @@
+import React, { useState, useEffect, useRef, useContext } from 'react'
+import JSZip from 'jszip'
+import axios from 'axios'
+import { PluginContext } from '../contexts/pluginContext'
+import { CustomTooltip } from '@remix-ui/helper'
+import { ImportExampleSelector } from './compile/ImportExampleSelector'
+import { TargetProjectSelector } from './compile/TargetProjectSelector'
+import { CompileStatusPanel } from './compile/CompileStatusPanel'
+import { FileUtil } from '../utils/fileutils'
+import { ModalDialog } from '@remix-ui/modal-dialog'
+
+const BASE_URL =
+ process.env.NODE_ENV === 'development'
+ ? process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_DEV
+ : process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_PROD
+
+const WS_URL =
+ process.env.NODE_ENV === 'development'
+ ? process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_DEV
+ : process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_PROD
+
+export const Compile = () => {
+ const [version] = useState('v0.85.0')
+ const [projectList, setProjectList] = useState([])
+ const [targetProject, setTargetProject] = useState('')
+ const [compileError, setCompileError] = useState(null)
+ const [compileLogs, setCompileLogs] = useState([])
+ const [loading, setLoading] = useState(false)
+ const [queuePosition, setQueuePosition] = useState(null)
+ const [examples, setExamples] = useState([])
+ const [exampleToImport, setExampleToImport] = useState('')
+ const wsRef = useRef(null)
+ const requestIdRef = useRef('')
+ const { plugin: client } = useContext(PluginContext)
+ const [modal, setModal] = useState({ hide: true, title: '', message: '', okLabel: 'Close' })
+
+ const showModal = (title: string, message: string) => {
+ setModal({ hide: false, title, message, okLabel: 'Close' })
+ }
+ const hideModal = () => setModal({ ...modal, hide: true })
+
+ useEffect(() => {
+ const fetchExamples = async () => {
+ try {
+ const res = await axios.get(`${BASE_URL}/examples`)
+ setExamples(res.data.examples)
+ } catch {
+ console.error('Failed to fetch examples')
+ }
+ }
+ fetchExamples()
+ }, [])
+
+ useEffect(() => {
+ getList()
+ return () => wsRef.current?.readyState === WebSocket.OPEN && wsRef.current.close()
+ }, [])
+
+ const generateUniqueId = () => {
+ const timestamp = new Date().toISOString().replace(/[-:.]/g, '')
+ const rand = Math.random().toString(36).substring(2, 8)
+ return `req_${timestamp}_${rand}`
+ }
+
+ const getList = async () => {
+ const projects = await getProjectHaveTomlFile('browser/aztec')
+ setProjectList(projects)
+ setTargetProject(projects[0] || '')
+ }
+
+ const setTarget = (e: { target: { value: string } }) => {
+ setTargetProject(e.target.value)
+ }
+
+ const getProjectHaveTomlFile = async (path: string): Promise => {
+ if (!client) return []
+ const projects: string[] = []
+ const findTomlFileRecursively = async (currentPath: string): Promise => {
+ const list = await client.call('fileManager', 'readdir', currentPath);
+ const hasTomlFile = Object.keys(list).some((item) => item.endsWith('Nargo.toml'))
+ if (hasTomlFile) {
+ projects.push(currentPath.replace('browser/', ''))
+ }
+ for (const [key, value] of Object.entries(list)) {
+ if ((value as any).isDirectory) {
+ const additionalPath = key.split('/').pop()
+ await findTomlFileRecursively(currentPath + '/' + additionalPath)
+ }
+ }
+ }
+ await findTomlFileRecursively(path)
+ return projects
+ }
+
+ const getAllProjectFiles = async (projectPath: string) => {
+ const files = await FileUtil.allFilesForBrowser(client, projectPath)
+ return files.filter((file) => !file.path.startsWith(`${projectPath}/target`))
+ }
+
+ const generateZip = async (files: any[], projectPath: string) => {
+ const zip = new JSZip()
+ await Promise.all(
+ files.map(async (file) => {
+ if (!file.isDirectory) {
+ const content = await client.call('fileManager', 'readFile', file.path);
+ const relativePath = file.path.replace('browser/', '')
+ const zipPath = relativePath.replace(`${projectPath}/`, '')
+ zip.file(zipPath, content)
+ }
+ })
+ )
+ return zip.generateAsync({ type: 'blob' })
+ }
+
+ const handleCompile = async () => {
+ if (!targetProject) {
+ showModal('Error', 'No target project selected!')
+ return
+ }
+
+ setLoading(true)
+ setCompileLogs([])
+ requestIdRef.current = generateUniqueId()
+
+ const ws = new WebSocket(`${WS_URL}`)
+ wsRef.current = ws
+
+ await new Promise((resolve, reject) => {
+ ws.onopen = () => {
+ ws.send(JSON.stringify({ requestId: requestIdRef.current }))
+ resolve()
+ }
+ ws.onerror = (error) => {
+ console.error('[Frontend] WebSocket connection error:', error)
+ reject(new Error('WebSocket connection failed'))
+ }
+ })
+
+ ws.onmessage = async (event) => {
+ try {
+ const parsed = JSON.parse(event.data)
+ if (parsed.logMsg) {
+ setCompileLogs((prev) => [...prev, parsed.logMsg])
+ await client.call('terminal', 'log', {
+ type: 'info',
+ value: parsed.logMsg
+ })
+ }
+ } catch (e) {
+ console.warn('[Frontend] Invalid WebSocket message:', event.data)
+ }
+ }
+
+ ws.onerror = () => {
+ showModal('Error', 'WebSocket connection failed')
+ setLoading(false)
+ }
+
+ try {
+ const projFiles = await getAllProjectFiles(targetProject)
+ const zipBlob = await generateZip(projFiles, targetProject)
+
+ const formData = new FormData()
+ formData.append('file', zipBlob, `${targetProject}.zip`)
+ formData.append('projectPath', targetProject)
+
+ const response = await axios.post(
+ `${BASE_URL}/compile?requestId=${requestIdRef.current}`,
+ formData
+ )
+
+ if (!response.data || !response.data.url) {
+ throw new Error('S3 URL not returned from backend')
+ }
+
+ const zipResponse = await axios.get(response.data.url, { responseType: 'arraybuffer' })
+ const compiledZip = await JSZip.loadAsync(zipResponse.data)
+
+ await Promise.all(
+ Object.entries(compiledZip.files).map(async ([path, file]) => {
+ if (!file.dir) {
+ const content = await file.async('string')
+ const remixPath = `browser/${targetProject}/${path}`
+ await client.call('fileManager', 'writeFile', remixPath, content)
+ }
+ })
+ )
+
+ await client.call('terminal', 'log', {
+ type: 'info',
+ value: 'Compilation completed!'
+ })
+ showModal('Success', `Compilation completed! JSON generated under ${targetProject}/target`)
+ } catch (error: any) {
+ showModal('Error', `Compilation failed: ${error.message}`)
+ await client.call('terminal', 'log', {
+ type: 'error',
+ value: `Compilation failed: ${error.message}`
+ })
+ } finally {
+ setLoading(false)
+ if (ws.readyState === WebSocket.OPEN) {
+ ws.close()
+ }
+ }
+ }
+
+ const checkQueueStatus = async () => {
+ try {
+ const res = await axios.get(`${BASE_URL}/queue/status`, {
+ params: { requestId: requestIdRef.current },
+ })
+ setQueuePosition(res.data.position)
+ } catch (err) {
+ console.warn('Failed to check queue status', err)
+ }
+ }
+
+ const importExample = async (exampleName: string) => {
+ if (!client) return
+ const targetPath = `browser/aztec/${exampleName}`
+
+ try {
+ const existing = await client.call('fileManager', 'readdir', targetPath)
+ if (Object.keys(existing).length > 0) {
+ await client.call('terminal', 'log', {
+ type: 'warn',
+ value: `⚠️ Project "${exampleName}" already exists. Import canceled.`
+ })
+ return
+ }
+ } catch (err) {}
+
+ try {
+ const res = await axios.get(`${BASE_URL}/examples/url`, {
+ params: { name: exampleName },
+ })
+
+ if (!res.data.url) throw new Error('No download URL received')
+
+ const zipRes = await axios.get(res.data.url, { responseType: 'arraybuffer' })
+ const zip = await JSZip.loadAsync(zipRes.data)
+ const rootFolder = Object.keys(zip.files)[0]?.split('/')[0]
+
+ await Promise.all(
+ Object.entries(zip.files).map(async ([zipPath, file]) => {
+ if (!file.dir && zipPath.startsWith(`${rootFolder}/`)) {
+ const relativePath = zipPath.replace(`${rootFolder}/`, '')
+ const remixPath = `${targetPath}/${relativePath}`
+ const content = await file.async('string')
+ await client.call('fileManager', 'writeFile', remixPath, content)
+ }
+ })
+ )
+
+ await client.call('terminal', 'log', {
+ type: 'info',
+ value: `Example "${exampleName}" imported.`
+ })
+
+ setTargetProject(`aztec/${exampleName}`)
+ await getList()
+ } catch (err: any) {
+ console.error(`Failed to import example ${exampleName}`, err)
+ await client.call('terminal', 'log', {
+ type: 'error',
+ value: `Failed to import ${exampleName}: ${err.message}`
+ })
+ }
+ }
+
+ return (
+ <>
+
+
+ Compiler Version:
+ {version}
+
+
+
+ setTargetProject(e.target.value)}
+ onReload={getList}
+ />
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/aztec-compiler/src/app/components/compile/CompileStatusPanel.tsx b/apps/aztec-compiler/src/app/components/compile/CompileStatusPanel.tsx
new file mode 100644
index 00000000000..d0dd9392793
--- /dev/null
+++ b/apps/aztec-compiler/src/app/components/compile/CompileStatusPanel.tsx
@@ -0,0 +1,18 @@
+import React from 'react'
+import { CustomTooltip } from '@remix-ui/helper'
+
+export const CompileStatusPanel = ({ loading, queuePosition, checkQueueStatus }) => {
+ if (!loading) return null
+ return (
+
+
+ {queuePosition !== null && (
+
+ You're currently #{queuePosition + 1} in the queue.
+
+ )}
+
+ )
+}
diff --git a/apps/aztec-compiler/src/app/components/compile/ImportExampleSelector.tsx b/apps/aztec-compiler/src/app/components/compile/ImportExampleSelector.tsx
new file mode 100644
index 00000000000..29b485962be
--- /dev/null
+++ b/apps/aztec-compiler/src/app/components/compile/ImportExampleSelector.tsx
@@ -0,0 +1,25 @@
+import React from 'react'
+import { CustomTooltip } from '@remix-ui/helper'
+
+export const ImportExampleSelector = ({ examples, exampleToImport, setExampleToImport, importExample }) => (
+
+
IMPORT EXAMPLE PROJECT
+
+
+
+
+
+)
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/app/components/compile/TargetProjectSelector.tsx b/apps/aztec-compiler/src/app/components/compile/TargetProjectSelector.tsx
new file mode 100644
index 00000000000..14fd2f1261d
--- /dev/null
+++ b/apps/aztec-compiler/src/app/components/compile/TargetProjectSelector.tsx
@@ -0,0 +1,26 @@
+import React from 'react'
+import { CustomTooltip } from '@remix-ui/helper'
+
+export const TargetProjectSelector = ({ projectList, targetProject, setTarget, onReload }) => (
+
+
+ TARGET PROJECT
+
+
+
+
+
+
+)
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/app/contexts/pluginContext.ts b/apps/aztec-compiler/src/app/contexts/pluginContext.ts
new file mode 100644
index 00000000000..d3753e39842
--- /dev/null
+++ b/apps/aztec-compiler/src/app/contexts/pluginContext.ts
@@ -0,0 +1,8 @@
+import { createContext } from 'react'
+import { PluginClient } from '@remixproject/plugin'
+
+export const PluginContext = createContext<{
+ plugin: PluginClient
+ dispatch: React.Dispatch
+ state: any
+}>(null as any)
diff --git a/apps/aztec-compiler/src/app/reducers/state.ts b/apps/aztec-compiler/src/app/reducers/state.ts
new file mode 100644
index 00000000000..771990349ea
--- /dev/null
+++ b/apps/aztec-compiler/src/app/reducers/state.ts
@@ -0,0 +1,8 @@
+export const initialState = {}
+
+export const pluginReducer = (state: any, action: any) => {
+ switch (action.type) {
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/app/services/aztecPluginClient.ts b/apps/aztec-compiler/src/app/services/aztecPluginClient.ts
new file mode 100644
index 00000000000..a63de295849
--- /dev/null
+++ b/apps/aztec-compiler/src/app/services/aztecPluginClient.ts
@@ -0,0 +1,22 @@
+import { PluginClient } from '@remixproject/plugin'
+import { createClient } from '@remixproject/plugin-webview'
+import EventManager from 'events'
+
+export class AztecPluginClient extends PluginClient {
+ public internalEvents: EventManager
+
+ constructor() {
+ super()
+ createClient(this)
+ this.internalEvents = new EventManager()
+ this.onload()
+ }
+
+ init(): void {
+ console.log('[aztec-plugin] Initialized!')
+ }
+
+ onActivation(): void {
+ this.internalEvents.emit('aztec_activated')
+ }
+}
diff --git a/apps/aztec-compiler/src/app/utils/fileutils.ts b/apps/aztec-compiler/src/app/utils/fileutils.ts
new file mode 100644
index 00000000000..20dc0c2c220
--- /dev/null
+++ b/apps/aztec-compiler/src/app/utils/fileutils.ts
@@ -0,0 +1,56 @@
+export interface FileInfo {
+ path: string;
+ isDirectory: boolean;
+}
+
+export class FileUtil {
+
+ static async allFilesForBrowser(client: any, dirName: string): Promise {
+ try {
+ let result: FileInfo[] = []
+ const files = await client?.fileManager.readdir('browser/' + dirName)
+ for (const [key, val] of Object.entries(files)) {
+ const file_ = {
+ path: key,
+ isDirectory: (val as any).isDirectory,
+ };
+ if (file_.isDirectory) {
+ const subDirFiles = (await FileUtil.allFilesForBrowser(client, file_.path)) || []
+
+ result = [...result, file_, ...subDirFiles]
+ } else {
+ result.push(file_)
+ }
+ }
+ return result
+ } catch (e) {
+ console.error(e)
+ return [];
+ }
+ }
+
+ static extractFilename(path: string): string {
+ const lastIndex = path.lastIndexOf('/')
+ if (lastIndex === -1) {
+ return path
+ }
+
+ return path.slice(lastIndex + 1)
+ }
+
+ static extractFilenameWithoutExtension(path: string): string {
+ const filename = FileUtil.extractFilename(path)
+ return filename.slice(0, filename.lastIndexOf('.'))
+ }
+
+ static async contents(fileManager: any, compileTarget: string, projFiles: FileInfo[]) {
+ return await Promise.all(
+ projFiles.map(async (u) => {
+ if (u.isDirectory) {
+ return ''
+ }
+ return await fileManager.readFile('browser/' + compileTarget + '/' + u.path)
+ }),
+ )
+ }
+}
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/css/app.css b/apps/aztec-compiler/src/css/app.css
new file mode 100644
index 00000000000..28bf8fe7857
--- /dev/null
+++ b/apps/aztec-compiler/src/css/app.css
@@ -0,0 +1,115 @@
+body {
+ font-size : .8rem;
+}
+.noir_section {
+ padding: 12px 24px 16px;
+}
+.noir_label {
+ margin-bottom: 2px;
+ font-size: 11px;
+ line-height: 12px;
+ text-transform: uppercase;
+}
+.noir_warnings_box {
+ display: flex;
+ align-items: center;
+}
+.noir_warnings_box label {
+ margin: 0;
+}
+.noir_config_section:hover {
+ cursor: pointer;
+}
+.noir_config_section {
+ font-size: 1rem;
+}
+.noir_config {
+ display: flex;
+ align-items: center;
+}
+.noir_config label {
+ margin: 0;
+}
+.noir_inner_label {
+ margin-bottom: 2px;
+ font-size: 11px;
+ line-height: 12px;
+ text-transform: uppercase;
+}
+.circuit_errors_box {
+ word-break: break-word;
+}
+.circuit_feedback.success,
+.circuit_feedback.error,
+.circuit_feedback.warning {
+ white-space: pre-line;
+ word-wrap: break-word;
+ cursor: pointer;
+ position: relative;
+ margin: 0.5em 0 1em 0;
+ border-radius: 5px;
+ line-height: 20px;
+ padding: 8px 15px;
+}
+
+.circuit_feedback.success pre,
+.circuit_feedback.error pre,
+.circuit_feedback.warning pre {
+ white-space: pre-line;
+ overflow-y: hidden;
+ background-color: transparent;
+ margin: 0;
+ font-size: 12px;
+ border: 0 none;
+ padding: 0;
+ border-radius: 0;
+}
+
+.circuit_feedback.success .close,
+.circuit_feedback.error .close,
+.circuit_feedback.warning .close {
+ visibility: hidden;
+ white-space: pre-line;
+ font-weight: bold;
+ position: absolute;
+ color: hsl(0, 0%, 0%); /* black in style-guide.js */
+ top: 0;
+ right: 0;
+ padding: 0.5em;
+}
+
+.circuit_feedback.success a,
+.circuit_feedback.error a,
+.circuit_feedback.warning a {
+ bottom: 0;
+ right: 0;
+}
+.custom-dropdown-items {
+ padding: 0.25rem 0.25rem;
+ border-radius: .25rem;
+ background: var(--custom-select);
+}
+.custom-dropdown-items a {
+ border-radius: .25rem;
+ text-transform: none;
+ text-decoration: none;
+ font-weight: normal;
+ font-size: 0.875rem;
+ padding: 0.25rem 0.25rem;
+ width: auto;
+ color: var(--text);
+}
+
+.compiler-version {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 13px;
+ color: #6c757d;
+ padding: 0 1rem 0.5rem 1rem;
+}
+
+.compiler-version-value {
+ color: #ffffff;
+ font-weight: 500;
+}
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/index.html b/apps/aztec-compiler/src/index.html
new file mode 100644
index 00000000000..a41a84c3875
--- /dev/null
+++ b/apps/aztec-compiler/src/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+ Aztec - Compiler
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/aztec-compiler/src/main.tsx b/apps/aztec-compiler/src/main.tsx
new file mode 100644
index 00000000000..502a6c93a3d
--- /dev/null
+++ b/apps/aztec-compiler/src/main.tsx
@@ -0,0 +1,9 @@
+import React from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './app/app'
+
+const container = document.getElementById('root')
+
+if (container) {
+ createRoot(container).render()
+}
\ No newline at end of file
diff --git a/apps/aztec-compiler/src/polyfills.ts b/apps/aztec-compiler/src/polyfills.ts
new file mode 100644
index 00000000000..2adf3d05b6f
--- /dev/null
+++ b/apps/aztec-compiler/src/polyfills.ts
@@ -0,0 +1,7 @@
+/**
+ * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
+ *
+ * See: https://github.com/zloirock/core-js#babel
+ */
+import 'core-js/stable';
+import 'regenerator-runtime/runtime';
diff --git a/apps/aztec-compiler/src/profile.json b/apps/aztec-compiler/src/profile.json
new file mode 100644
index 00000000000..6a1c0ae6661
--- /dev/null
+++ b/apps/aztec-compiler/src/profile.json
@@ -0,0 +1,17 @@
+{
+ "name": "aztec-compiler",
+ "kind": "provider",
+ "displayName": "Aztec Compiler",
+ "events": [],
+ "version": "2.0.0",
+ "methods": [],
+ "canActivate": [],
+ "url": "",
+ "description": "Enables support for aztec contract compilation",
+ "icon": "assets/img/noir-icon12.webp",
+ "location": "sidePanel",
+ "documentation": "",
+ "repo": "https://github.com/ethereum/remix-project/tree/master/apps/aztec-compiler",
+ "maintainedBy": "Remix",
+ "authorContact": ""
+}
diff --git a/apps/aztec-compiler/tsconfig.app.json b/apps/aztec-compiler/tsconfig.app.json
new file mode 100644
index 00000000000..2272b8a388c
--- /dev/null
+++ b/apps/aztec-compiler/tsconfig.app.json
@@ -0,0 +1,24 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "types": ["node"]
+ },
+ "files": [
+ "../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
+ "../../node_modules/@nrwl/react/typings/image.d.ts"
+ ],
+ "exclude": [
+ "jest.config.ts",
+ "**/*.spec.ts",
+ "**/*.test.ts",
+ "**/*.spec.tsx",
+ "**/*.test.tsx",
+ "**/*.spec.js",
+ "**/*.test.js",
+ "**/*.spec.jsx",
+ "**/*.test.jsx"
+ ],
+ "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
+ }
+
\ No newline at end of file
diff --git a/apps/aztec-compiler/tsconfig.json b/apps/aztec-compiler/tsconfig.json
new file mode 100644
index 00000000000..5aab5e79111
--- /dev/null
+++ b/apps/aztec-compiler/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "allowJs": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ]
+}
diff --git a/apps/aztec-compiler/webpack.config.js b/apps/aztec-compiler/webpack.config.js
new file mode 100644
index 00000000000..5a08c8e89e6
--- /dev/null
+++ b/apps/aztec-compiler/webpack.config.js
@@ -0,0 +1,113 @@
+const { composePlugins, withNx } = require('@nrwl/webpack')
+const webpack = require('webpack')
+const TerserPlugin = require("terser-webpack-plugin")
+const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
+const path = require('path')
+
+// Nx plugins for webpack.
+module.exports = composePlugins(withNx(), (config) => {
+
+ // add fallback for node modules
+ config.resolve.fallback = {
+ ...config.resolve.fallback,
+ "crypto": require.resolve("crypto-browserify"),
+ "stream": require.resolve("stream-browserify"),
+ "path": require.resolve("path-browserify"),
+ "http": require.resolve("stream-http"),
+ "https": require.resolve("https-browserify"),
+ "constants": require.resolve("constants-browserify"),
+ "os": false, //require.resolve("os-browserify/browser"),
+ "timers": false, // require.resolve("timers-browserify"),
+ "zlib": require.resolve("browserify-zlib"),
+ "fs": false,
+ "module": false,
+ "tls": false,
+ "net": false,
+ "readline": false,
+ "child_process": false,
+ "buffer": require.resolve("buffer/"),
+ "vm": require.resolve('vm-browserify'),
+ }
+
+
+ // add externals
+ config.externals = {
+ ...config.externals,
+ solc: 'solc',
+ }
+
+ // add public path
+ config.output.publicPath = './'
+
+ // add copy & provide plugin
+ config.plugins.push(
+ new webpack.ProvidePlugin({
+ Buffer: ['buffer', 'Buffer'],
+ url: ['url', 'URL'],
+ process: 'process/browser',
+ })
+ )
+
+ // set the define plugin to load the WALLET_CONNECT_PROJECT_ID
+ config.plugins.push(
+ new webpack.DefinePlugin({
+ WALLET_CONNECT_PROJECT_ID: JSON.stringify(process.env.WALLET_CONNECT_PROJECT_ID),
+ })
+ )
+
+ config.plugins.push(
+ new webpack.DefinePlugin({
+ 'fetch': `((...args) => {
+ if (args[0].origin === 'https://github.com') {
+ return fetch('https://api.allorigins.win/raw?url=' + args[0])
+ }
+ return fetch(...args)
+ })`,
+ })
+ )
+
+ // source-map loader
+ config.module.rules.push({
+ test: /\.js$/,
+ use: ["source-map-loader"],
+ enforce: "pre"
+ })
+
+ config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
+
+
+ // set minimizer
+ config.optimization.minimizer = [
+ new TerserPlugin({
+ parallel: true,
+ terserOptions: {
+ ecma: 2015,
+ compress: false,
+ mangle: false,
+ format: {
+ comments: false,
+ },
+ },
+ extractComments: false,
+ }),
+ new CssMinimizerPlugin(),
+ ];
+
+ config.watchOptions = {
+ ignored: /node_modules/
+ }
+
+ config.experiments.syncWebAssembly = true
+
+ config.plugins.push(
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
+ 'process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_DEV': JSON.stringify(process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_DEV),
+ 'process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_PROD': JSON.stringify(process.env.REACT_APP_AZTEC_PLUGIN_API_BASE_URL_PROD),
+ 'process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_DEV': JSON.stringify(process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_DEV),
+ 'process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_PROD': JSON.stringify(process.env.REACT_APP_AZTEC_PLUGIN_WS_URL_PROD),
+ })
+ )
+
+ return config;
+});
diff --git a/apps/remix-ide/project.json b/apps/remix-ide/project.json
index 744036b2454..a7e64387054 100644
--- a/apps/remix-ide/project.json
+++ b/apps/remix-ide/project.json
@@ -3,7 +3,7 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/remix-ide/src",
"projectType": "application",
- "implicitDependencies": ["doc-gen", "doc-viewer", "contract-verification", "vyper", "solhint", "circuit-compiler", "learneth", "quick-dapp", "remix-dapp", "noir-compiler"],
+ "implicitDependencies": ["doc-gen", "doc-viewer", "contract-verification", "vyper", "solhint", "circuit-compiler", "learneth", "quick-dapp", "remix-dapp", "noir-compiler", "aztec-compiler"],
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
diff --git a/apps/remix-ide/src/app/plugins/matomo.ts b/apps/remix-ide/src/app/plugins/matomo.ts
index 40c61e718e7..748e053c5cd 100644
--- a/apps/remix-ide/src/app/plugins/matomo.ts
+++ b/apps/remix-ide/src/app/plugins/matomo.ts
@@ -11,7 +11,7 @@ const profile = {
version: '1.0.0'
}
-const allowedPlugins = ['LearnEth', 'etherscan', 'vyper', 'circuit-compiler', 'doc-gen', 'doc-viewer', 'solhint', 'walletconnect', 'scriptRunner', 'scriptRunnerBridge', 'dgit', 'contract-verification', 'noir-compiler']
+const allowedPlugins = ['LearnEth', 'etherscan', 'vyper', 'circuit-compiler', 'doc-gen', 'doc-viewer', 'solhint', 'walletconnect', 'scriptRunner', 'scriptRunnerBridge', 'dgit', 'contract-verification', 'noir-compiler', 'aztec-compiler']
export class Matomo extends Plugin {
diff --git a/apps/remix-ide/src/remixAppManager.ts b/apps/remix-ide/src/remixAppManager.ts
index 2e048de25e0..93b3abeecc7 100644
--- a/apps/remix-ide/src/remixAppManager.ts
+++ b/apps/remix-ide/src/remixAppManager.ts
@@ -97,7 +97,7 @@ let requiredModules = [
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)
const dependentModules = ['foundry', 'hardhat', 'truffle', 'slither']
-const loadLocalPlugins = ['doc-gen', 'doc-viewer', 'contract-verification', 'vyper', 'solhint', 'circuit-compiler', 'learneth', 'quick-dapp', 'noir-compiler']
+const loadLocalPlugins = ['doc-gen', 'doc-viewer', 'contract-verification', 'vyper', 'solhint', 'circuit-compiler', 'learneth', 'quick-dapp', 'noir-compiler', 'aztec-compiler']
const partnerPlugins = ['cookbookdev']
@@ -153,7 +153,8 @@ export function isNative(name) {
'contract-verification',
'popupPanel',
'LearnEth',
- 'noir-compiler'
+ 'noir-compiler',
+ 'aztec-compiler',
]
return nativePlugins.includes(name) || requiredModules.includes(name) || isInjectedProvider(name) || isVM(name) || isScriptRunner(name)
}