From 89e6c0ce1dc12fff603a70d52644a9323ac2e4b9 Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Tue, 16 Jul 2024 22:13:06 +0100 Subject: [PATCH] Install circom via cli --- .gitignore | 1 + .../src/app/services/circomPluginClient.ts | 296 +++++++++--------- apps/remix-ide/src/app.js | 6 +- .../plugins/electron/circomElectronPlugin.ts | 12 + apps/remix-ide/src/remixAppManager.js | 2 +- apps/remix-ide/src/remixEngine.js | 1 + apps/remixdesktop/package.json | 22 +- apps/remixdesktop/src/engine.ts | 3 + .../src/plugins/circomElectronBasePlugin.ts | 52 +++ apps/remixdesktop/src/preload.ts | 4 +- apps/remixdesktop/src/tools/circom.ts | 55 ++++ apps/remixdesktop/yarn.lock | 83 ++++- 12 files changed, 385 insertions(+), 152 deletions(-) create mode 100644 apps/remix-ide/src/app/plugins/electron/circomElectronPlugin.ts create mode 100644 apps/remixdesktop/src/plugins/circomElectronBasePlugin.ts create mode 100644 apps/remixdesktop/src/tools/circom.ts diff --git a/.gitignore b/.gitignore index 9e40832324..48697ac7dd 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,5 @@ apps/remix-ide/src/assets/esbuild.wasm apps/remixdesktop/build* apps/remixdesktop/reports apps/remixdesktop/logs/ +apps/remixdesktop/bin/ logs diff --git a/apps/circuit-compiler/src/app/services/circomPluginClient.ts b/apps/circuit-compiler/src/app/services/circomPluginClient.ts index 15bfa518a0..ca4f2cd5c4 100644 --- a/apps/circuit-compiler/src/app/services/circomPluginClient.ts +++ b/apps/circuit-compiler/src/app/services/circomPluginClient.ts @@ -8,7 +8,8 @@ import * as compilerV217 from 'circom_wasm/v2.1.7' import * as compilerV216 from 'circom_wasm/v2.1.6' import * as compilerV215 from 'circom_wasm/v2.1.5' import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' -import { CompilationConfig, CompilerReport, PrimeValue, ResolverOutput } from '../types' +import { CompilationConfig, CompilerReport, PrimeValue } from '../types' +import isElectron from 'is-electron' export class CircomPluginClient extends PluginClient { public internalEvents: EventManager @@ -61,179 +62,194 @@ export class CircomPluginClient extends PluginClient { } async parse(path: string, fileContent?: string): Promise<[CompilerReport[], Record]> { - if (!fileContent) { + if (isElectron()) { // @ts-ignore - fileContent = await this.call('fileManager', 'readFile', path) - } - this.lastParsedFiles = await this.resolveDependencies(path, fileContent) - const parsedOutput = this.compiler ? this.compiler.parse(path, this.lastParsedFiles) : parse(path, this.lastParsedFiles) + return await this.call('circom', 'parse', path) + } else { + if (!fileContent) { + // @ts-ignore + fileContent = await this.call('fileManager', 'readFile', path) + } + this.lastParsedFiles = await this.resolveDependencies(path, fileContent) + const parsedOutput = this.compiler ? this.compiler.parse(path, this.lastParsedFiles) : parse(path, this.lastParsedFiles) - try { - const result: CompilerReport[] = JSON.parse(parsedOutput.report()) - const mapReportFilePathToId: Record = {} + try { + const result: CompilerReport[] = JSON.parse(parsedOutput.report()) + const mapReportFilePathToId: Record = {} - if (result.length === 0) { - // @ts-ignore - await this.call('editor', 'clearErrorMarkers', [path]) - } else { - const markers = [] + if (result.length === 0) { + // @ts-ignore + await this.call('editor', 'clearErrorMarkers', [path]) + } else { + const markers = [] - for (const report of result) { - for (const label in report.labels) { - const file_id = report.labels[label].file_id + for (const report of result) { + for (const label in report.labels) { + const file_id = report.labels[label].file_id - mapReportFilePathToId[file_id] = parsedOutput.get_report_name(parseInt(file_id)) - if (file_id === '0') { - // @ts-ignore - const startPosition: { lineNumber: number; column: number } = await this.call( - 'editor', + mapReportFilePathToId[file_id] = parsedOutput.get_report_name(parseInt(file_id)) + if (file_id === '0') { // @ts-ignore - 'getPositionAt', - report.labels[label].range.start - ) - // @ts-ignore - const endPosition: { lineNumber: number; column: number } = await this.call( - 'editor', + const startPosition: { lineNumber: number; column: number } = await this.call( + 'editor', + // @ts-ignore + 'getPositionAt', + report.labels[label].range.start + ) // @ts-ignore - 'getPositionAt', - report.labels[label].range.end - ) - - markers.push({ - message: report.message, - severity: report.type.toLowerCase(), - position: { - start: { - line: startPosition.lineNumber, - column: startPosition.column, + const endPosition: { lineNumber: number; column: number } = await this.call( + 'editor', + // @ts-ignore + 'getPositionAt', + report.labels[label].range.end + ) + + markers.push({ + message: report.message, + severity: report.type.toLowerCase(), + position: { + start: { + line: startPosition.lineNumber, + column: startPosition.column, + }, + end: { + line: endPosition.lineNumber, + column: endPosition.column, + }, }, - end: { - line: endPosition.lineNumber, - column: endPosition.column, - }, - }, - file: path, - }) + file: path, + }) + } } } - } - if (markers.length > 0) { - // @ts-ignore - await this.call('editor', 'addErrorMarker', markers) - } else { - // @ts-ignore - await this.call('editor', 'clearErrorMarkers', [path]) - this.emit('statusChanged', { key: 'none' }) + if (markers.length > 0) { + // @ts-ignore + await this.call('editor', 'addErrorMarker', markers) + } else { + // @ts-ignore + await this.call('editor', 'clearErrorMarkers', [path]) + this.emit('statusChanged', { key: 'none' }) + } } - } - return [result, mapReportFilePathToId] - } catch (e) { - throw new Error(e) + return [result, mapReportFilePathToId] + } catch (e) { + throw new Error(e) + } } } async compile(path: string, compilationConfig?: CompilationConfig): Promise { - this.internalEvents.emit('circuit_compiling_start') - this.emit('statusChanged', { key: 'loading', title: 'Compiling...', type: 'info' }) - // @ts-ignore - this.call('terminal', 'log', { type: 'log', value: 'Compiling ' + path }) - const [parseErrors, filePathToId] = await this.parse(path) - - if (parseErrors && (parseErrors.length > 0)) { - if (parseErrors[0].type === 'Error') { - this.internalEvents.emit('circuit_parsing_errored', parseErrors, filePathToId) - this.logCompilerReport(parseErrors) - return - } else if (parseErrors[0].type === 'Warning') { - this.internalEvents.emit('circuit_parsing_warning', parseErrors, filePathToId) - this.logCompilerReport(parseErrors) - } + if (isElectron()) { + // @ts-ignore + return await this.call('circom', 'compile', path) } else { - this.internalEvents.emit('circuit_parsing_done', parseErrors, filePathToId) - this.emit('statusChanged', { key: 'succeed', title: 'circuit compiled successfully', type: 'success' }) - } - if (compilationConfig) { - const { prime, version } = compilationConfig + this.internalEvents.emit('circuit_compiling_start') + this.emit('statusChanged', { key: 'loading', title: 'Compiling...', type: 'info' }) + // @ts-ignore + this.call('terminal', 'log', { type: 'log', value: 'Compiling ' + path }) + const [parseErrors, filePathToId] = await this.parse(path) + + if (parseErrors && (parseErrors.length > 0)) { + if (parseErrors[0].type === 'Error') { + this.internalEvents.emit('circuit_parsing_errored', parseErrors, filePathToId) + this.logCompilerReport(parseErrors) + return + } else if (parseErrors[0].type === 'Warning') { + this.internalEvents.emit('circuit_parsing_warning', parseErrors, filePathToId) + this.logCompilerReport(parseErrors) + } + } else { + this.internalEvents.emit('circuit_parsing_done', parseErrors, filePathToId) + this.emit('statusChanged', { key: 'succeed', title: 'circuit compiled successfully', type: 'success' }) + } + if (compilationConfig) { + const { prime, version } = compilationConfig - this.compilerVersion = version - this.compilerPrime = prime - } - const circuitApi = this.compiler ? this.compiler.compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) : compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) - const circuitProgram = circuitApi.program() + this.compilerVersion = version + this.compilerPrime = prime + } + const circuitApi = this.compiler ? this.compiler.compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) : compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) + const circuitProgram = circuitApi.program() - if (circuitProgram.length < 1) { - const circuitErrors = circuitApi.report() + if (circuitProgram.length < 1) { + const circuitErrors = circuitApi.report() - this.logCompilerReport(circuitErrors) - this._paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation failed']) - throw new Error(circuitErrors) - } else { - this.lastCompiledFile = path - const fileName = extractNameFromKey(path) + this.logCompilerReport(circuitErrors) + this._paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation failed']) + throw new Error(circuitErrors) + } else { + this.lastCompiledFile = path + const fileName = extractNameFromKey(path) - this.lastCompiledCircuitPath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'wasm') - // @ts-ignore - await this.call('fileManager', 'writeFile', this.lastCompiledCircuitPath, circuitProgram, { encoding: null }) - const fileContent = this.lastParsedFiles[path] - const searchComponentName = fileContent.match(/component\s+main\s*(?:{[^{}]*})?\s*=\s*([A-Za-z_]\w*)\s*\(.*\)/) + this.lastCompiledCircuitPath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'wasm') + // @ts-ignore + await this.call('fileManager', 'writeFile', this.lastCompiledCircuitPath, circuitProgram, { encoding: null }) + const fileContent = this.lastParsedFiles[path] + const searchComponentName = fileContent.match(/component\s+main\s*(?:{[^{}]*})?\s*=\s*([A-Za-z_]\w*)\s*\(.*\)/) - if (searchComponentName) { - const componentName = searchComponentName[1] - const signals = circuitApi.input_signals(componentName) + if (searchComponentName) { + const componentName = searchComponentName[1] + const signals = circuitApi.input_signals(componentName) - this.internalEvents.emit('circuit_compiling_done', signals) - } else { - this.internalEvents.emit('circuit_compiling_done', []) + this.internalEvents.emit('circuit_compiling_done', signals) + } else { + this.internalEvents.emit('circuit_compiling_done', []) + } + this._paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation successful']) + circuitApi.log().map(log => { + log && this.call('terminal', 'log', { type: 'log', value: log }) + }) + // @ts-ignore + this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' }) } - this._paq.push(['trackEvent', 'circuit-compiler', 'compile', 'Compilation successful']) - circuitApi.log().map(log => { - log && this.call('terminal', 'log', { type: 'log', value: log }) - }) - // @ts-ignore - this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' }) } } async generateR1cs (path: string, compilationConfig?: CompilationConfig): Promise { - const [parseErrors, filePathToId] = await this.parse(path) - - if (parseErrors && (parseErrors.length > 0)) { - if (parseErrors[0].type === 'Error') { - this.logCompilerReport(parseErrors) - return - } else if (parseErrors[0].type === 'Warning') { - this.logCompilerReport(parseErrors) + if (isElectron()) { + // @ts-ignore + return await this.call('circom', 'generateR1cs', path) + } else { + const [parseErrors, filePathToId] = await this.parse(path) + + if (parseErrors && (parseErrors.length > 0)) { + if (parseErrors[0].type === 'Error') { + this.logCompilerReport(parseErrors) + return + } else if (parseErrors[0].type === 'Warning') { + this.logCompilerReport(parseErrors) + } } - } - if (compilationConfig) { - const { prime, version } = compilationConfig + if (compilationConfig) { + const { prime, version } = compilationConfig - this.compilerVersion = version - this.compilerPrime = prime - } - const r1csApi = this.compiler ? this.compiler.generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) : generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) - const r1csProgram = r1csApi.program() + this.compilerVersion = version + this.compilerPrime = prime + } + const r1csApi = this.compiler ? this.compiler.generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) : generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) + const r1csProgram = r1csApi.program() - if (r1csProgram.length < 1) { - const r1csErrors = r1csApi.report() + if (r1csProgram.length < 1) { + const r1csErrors = r1csApi.report() - this.logCompilerReport(r1csErrors) - this._paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation failed']) - throw new Error(r1csErrors) - } else { - const fileName = extractNameFromKey(path) - const writePath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'r1cs') + this.logCompilerReport(r1csErrors) + this._paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation failed']) + throw new Error(r1csErrors) + } else { + const fileName = extractNameFromKey(path) + const writePath = extractParentFromKey(path) + "/.bin/" + fileName.replace('circom', 'r1cs') - // @ts-ignore - await this.call('fileManager', 'writeFile', writePath, r1csProgram, true) - this._paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation successful']) - r1csApi.log().map(log => { - log && this.call('terminal', 'log', { type: 'log', value: log }) - }) - // @ts-ignore - this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' }) + // @ts-ignore + await this.call('fileManager', 'writeFile', writePath, r1csProgram, true) + this._paq.push(['trackEvent', 'circuit-compiler', 'generateR1cs', 'R1CS Generation successful']) + r1csApi.log().map(log => { + log && this.call('terminal', 'log', { type: 'log', value: log }) + }) + // @ts-ignore + this.call('terminal', 'log', { type: 'typewritersuccess', value: 'Everything went okay' }) + } } } diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 23addcdf90..ab3b9ff246 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -66,7 +66,7 @@ import { FoundryHandle } from './app/files/foundry-handle' import { FoundryHandleDesktop } from './app/plugins/electron/foundryPlugin' import { HardhatHandle } from './app/files/hardhat-handle' import { HardhatHandleDesktop } from './app/plugins/electron/hardhatPlugin' - +import { circomPlugin } from './app/plugins/electron/circomElectronPlugin' import { GitPlugin } from './app/plugins/git' import { Matomo } from './app/plugins/matomo' @@ -419,6 +419,8 @@ class AppComponent { this.engine.register([xterm]) const ripgrep = new ripgrepPlugin() this.engine.register([ripgrep]) + const circom = new circomPlugin() + this.engine.register([circom]) const appUpdater = new appUpdaterPlugin() this.engine.register([appUpdater]) const remixAIDesktop = new remixAIDesktopPlugin() @@ -565,7 +567,7 @@ class AppComponent { await this.appManager.activatePlugin(['solidity-script', 'remix-templates']) if (isElectron()) { - await this.appManager.activatePlugin(['isogit', 'electronconfig', 'electronTemplates', 'xterm', 'ripgrep', 'appUpdater', 'slither', 'foundry', 'hardhat']) // 'remixAID' + await this.appManager.activatePlugin(['isogit', 'electronconfig', 'electronTemplates', 'xterm', 'ripgrep', 'appUpdater', 'slither', 'foundry', 'hardhat', 'circom']) // 'remixAID' } this.appManager.on( diff --git a/apps/remix-ide/src/app/plugins/electron/circomElectronPlugin.ts b/apps/remix-ide/src/app/plugins/electron/circomElectronPlugin.ts new file mode 100644 index 0000000000..ef45b39343 --- /dev/null +++ b/apps/remix-ide/src/app/plugins/electron/circomElectronPlugin.ts @@ -0,0 +1,12 @@ +import { ElectronPlugin } from '@remixproject/engine-electron' + +export class circomPlugin extends ElectronPlugin { + constructor() { + super({ + displayName: 'circom', + name: 'circom', + description: 'circom language compiler', + }) + this.methods = [] + } +} diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index 9d6938f134..2f046d0556 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -171,7 +171,7 @@ export class RemixAppManager extends PluginManager { this.pluginsDirectory = 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json' this.pluginLoader = new PluginLoader() if (Registry.getInstance().get('platform').api.isDesktop()) { - requiredModules = [...requiredModules, 'fs', 'electronTemplates', 'isogit', 'remix-templates', 'electronconfig', 'xterm', 'compilerloader', 'ripgrep', 'slither', 'remixAID'] + requiredModules = [...requiredModules, 'fs', 'electronTemplates', 'isogit', 'remix-templates', 'electronconfig', 'xterm', 'compilerloader', 'ripgrep', 'slither', 'remixAID', 'circom'] } } diff --git a/apps/remix-ide/src/remixEngine.js b/apps/remix-ide/src/remixEngine.js index f81bcb5037..b883655e55 100644 --- a/apps/remix-ide/src/remixEngine.js +++ b/apps/remix-ide/src/remixEngine.js @@ -30,6 +30,7 @@ export class RemixEngine extends Engine { if (name === 'remixAI') return { queueTimeout: 60000 * 20 } if (name === 'cookbookdev') return { queueTimeout: 60000 * 3 } if (name === 'contentImport') return { queueTimeout: 60000 * 3 } + if (name === 'circom') return { queueTimeout: 60000 * 4 } return { queueTimeout: 10000 } } diff --git a/apps/remixdesktop/package.json b/apps/remixdesktop/package.json index 9020b130fc..3b63f098f4 100644 --- a/apps/remixdesktop/package.json +++ b/apps/remixdesktop/package.json @@ -21,8 +21,25 @@ }, "homepage": "https://github.com/ethereum/remix-project#readme", "appId": "org.ethereum.remixdesktop", - "mac": { - "category": "public.app-category.productivity" + "build": { + "files": [ + "build/**/*" + ], + "mac": { + "category": "public.app-category.productivity", + "icon": "assets/icon.png", + "darkModeSupport": true, + "hardenedRuntime": true, + "gatekeeperAssess": false, + "entitlements": "entitlements.mac.plist", + "entitlementsInherit": "entitlements.mac.plist", + "extraResources": [ + { + "from": "bin/circom-macos-amd64", + "to": "bin/circom-macos-amd64" + } + ] + } }, "scripts": { "start:dev": "yarn webpack --config webpack.config.js && electron --inspect=5858 .", @@ -75,6 +92,7 @@ "axios": "^1.7.4", "byline": "^5.0.0", "chokidar": "^3.5.3", + "dockerode": "^4.0.2", "electron-updater": "^6.1.8", "express": "^4.20.0", "isomorphic-git": "^1.24.2", diff --git a/apps/remixdesktop/src/engine.ts b/apps/remixdesktop/src/engine.ts index 7fc425033e..7c573a752f 100644 --- a/apps/remixdesktop/src/engine.ts +++ b/apps/remixdesktop/src/engine.ts @@ -14,6 +14,7 @@ import { AppUpdaterPlugin } from './plugins/appUpdater'; import { RemixAIDesktopPlugin } from './plugins/remixAIDektop'; import { FoundryPlugin } from './plugins/foundryPlugin'; import { HardhatPlugin } from './plugins/hardhatPlugin'; +import { CircomElectronPlugin } from './plugins/circomElectronBasePlugin'; import { isE2E } from './main'; const engine = new Engine() @@ -30,6 +31,7 @@ const appUpdaterPlugin = new AppUpdaterPlugin() const foundryPlugin = new FoundryPlugin() const hardhatPlugin = new HardhatPlugin() const remixAIDesktopPlugin = new RemixAIDesktopPlugin() +const circomPlugin = new CircomElectronPlugin() engine.register(appManager) engine.register(fsPlugin) @@ -44,6 +46,7 @@ engine.register(foundryPlugin) engine.register(appUpdaterPlugin) engine.register(hardhatPlugin) engine.register(remixAIDesktopPlugin) +engine.register(circomPlugin) appManager.activatePlugin('electronconfig') appManager.activatePlugin('fs') diff --git a/apps/remixdesktop/src/plugins/circomElectronBasePlugin.ts b/apps/remixdesktop/src/plugins/circomElectronBasePlugin.ts new file mode 100644 index 0000000000..fd2f58df95 --- /dev/null +++ b/apps/remixdesktop/src/plugins/circomElectronBasePlugin.ts @@ -0,0 +1,52 @@ +import { ElectronBasePlugin, ElectronBasePluginClient } from "@remixproject/plugin-electron" +import { Profile } from "@remixproject/plugin-utils" +import { circomCli } from "../tools/circom" + +const profile: Profile = { + displayName: 'circom', + name: 'circom', + description: 'Circom language compiler' +} + +export class CircomElectronPlugin extends ElectronBasePlugin { + clients: CircomElectronPluginClient[] = [] + + constructor() { + super(profile, clientProfile, CircomElectronPluginClient) + this.methods = [...super.methods] + } + + async onActivation(): Promise { + console.log('activating to exec') + if (!(await circomCli.isCargoInstalled())) await circomCli.installRustup() + if (!(await circomCli.isCircomInstalled())) await circomCli.installCircom() + } +} + +const clientProfile: Profile = { + name: 'circom', + displayName: 'circom', + description: 'Circom Language Compiler', + methods: ['parse', 'compile', 'generateR1cs'] +} + +class CircomElectronPluginClient extends ElectronBasePluginClient { + circomIsInstalled: boolean = false + + constructor(webContentsId: number, profile: Profile) { + super(webContentsId, profile) + this.onload() + } + + async compile() { + console.log('compiling circom circuit...') + } + + parse(): void { + console.log('parsing circom electron plugin...') + } + + generateR1cs(): void { + console.log('generating r1cs circom electron plugin...') + } +} \ No newline at end of file diff --git a/apps/remixdesktop/src/preload.ts b/apps/remixdesktop/src/preload.ts index f82de04f79..6eb9d71744 100644 --- a/apps/remixdesktop/src/preload.ts +++ b/apps/remixdesktop/src/preload.ts @@ -6,7 +6,7 @@ console.log('preload.ts', new Date().toLocaleTimeString()) /* preload script needs statically defined API for each plugin */ -const exposedPLugins = ['fs', 'git', 'xterm', 'isogit', 'electronconfig', 'electronTemplates', 'ripgrep', 'compilerloader', 'appUpdater', 'slither', 'foundry', 'hardhat', 'remixAID'] +const exposedPLugins = ['fs', 'git', 'xterm', 'isogit', 'electronconfig', 'electronTemplates', 'ripgrep', 'compilerloader', 'appUpdater', 'slither', 'foundry', 'hardhat', 'remixAID', 'circom'] let webContentsId: number | undefined @@ -18,7 +18,7 @@ contextBridge.exposeInMainWorld('electronAPI', { isPackaged: () => ipcRenderer.invoke('config:isPackaged'), isE2E: () => ipcRenderer.invoke('config:isE2E'), canTrackMatomo: () => ipcRenderer.invoke('config:canTrackMatomo'), - trackEvent: (args: any[]) => ipcRenderer.invoke('matomo:trackEvent', args), + trackEvent: (args: any[]) => ipcRenderer.invoke('matomo:trackEvent', args), openFolder: (path: string) => ipcRenderer.invoke('fs:openFolder', webContentsId, path), openFolderInSameWindow: (path: string) => ipcRenderer.invoke('fs:openFolderInSameWindow', webContentsId, path), activatePlugin: (name: string) => { diff --git a/apps/remixdesktop/src/tools/circom.ts b/apps/remixdesktop/src/tools/circom.ts new file mode 100644 index 0000000000..7336bf9310 --- /dev/null +++ b/apps/remixdesktop/src/tools/circom.ts @@ -0,0 +1,55 @@ +import { app } from 'electron' +import { promisify } from 'util' +import { exec } from 'child_process' +import { gitProxy } from './git' +import path from 'path' +import { existsSync } from 'fs' + +const execAsync = promisify(exec) + +export const circomCli = { + async installRustup () { + try { + console.log('installing rustup') + const { stdout } = await execAsync(`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y`) + + console.log('stdout: ', stdout) + } catch (e) { + console.error(e) + } + }, + + async installCircom () { + try { + const appPath = app.getAppPath() + const targetPath = path.join(appPath, 'bin') + + console.log('cloning circom repo to ' + targetPath) + if (!existsSync(`${targetPath}/circom`)) await gitProxy.clone('https://github.com/iden3/circom.git', targetPath) + console.log('builing circom with cargo') + await execAsync(`cd ${targetPath}/circom && cargo build --release && cargo install --path circom`) + } catch (e) { + console.error(e) + } + }, + + async isCircomInstalled () { + try { + await execAsync(`circom --version`) + + return true + } catch (e) { + return false + } + }, + + async isCargoInstalled () { + try { + await execAsync(`cargo version`) + + return true + } catch (e) { + return false + } + } +} \ No newline at end of file diff --git a/apps/remixdesktop/yarn.lock b/apps/remixdesktop/yarn.lock index 83d6645f63..7b7c99e731 100644 --- a/apps/remixdesktop/yarn.lock +++ b/apps/remixdesktop/yarn.lock @@ -14,6 +14,11 @@ dependencies: regenerator-runtime "^0.14.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@develar/schema-utils@~2.6.5": version "2.6.5" resolved "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz" @@ -1724,7 +1729,7 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asn1@~0.2.3: +asn1@^0.2.6, asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== @@ -1853,7 +1858,7 @@ base64-js@^1.3.1, base64-js@^1.5.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bcrypt-pbkdf@^1.0.0: +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -2088,6 +2093,11 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "^4.3.0" +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + builder-util-runtime@9.2.3: version "9.2.3" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.3.tgz#0a82c7aca8eadef46d67b353c638f052c206b83c" @@ -2234,7 +2244,7 @@ chokidar@3.5.3, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.4: +chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -2491,6 +2501,14 @@ cors@^2.8.1: object-assign "^4" vary "^1" +cpu-features@~0.0.9: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.10.tgz#9aae536db2710c7254d7ed67cb3cbc7d29ad79c5" + integrity sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA== + dependencies: + buildcheck "~0.0.6" + nan "^2.19.0" + crc-32@^1.2.0: version "1.2.2" resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" @@ -2790,6 +2808,25 @@ dmg-license@^1.0.11: smart-buffer "^4.0.2" verror "^1.10.0" +docker-modem@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-5.0.3.tgz#50c06f11285289f58112b5c4c4d89824541c41d0" + integrity sha512-89zhop5YVhcPEt5FpUFGr3cDyceGhq/F9J+ZndQ4KfqNvfbJpPMfgeixFgUj5OjCYAboElqODxY5Z1EBsSa6sg== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.15.0" + +dockerode@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-4.0.2.tgz#dedc8529a1db3ac46d186f5912389899bc309f7d" + integrity sha512-9wM1BVpVMFr2Pw3eJNXrYYt6DT9k0xMcsSCjtPvyQ+xa1iPg/Mo3T/gUcwI0B2cczqCeCYRPF8yFYDwtFXT0+w== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^5.0.3" + tar-fs "~2.0.1" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -5148,6 +5185,11 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -5277,6 +5319,11 @@ nan@^2.17.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== +nan@^2.18.0, nan@^2.19.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" + integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -5841,7 +5888,7 @@ read-config-file@6.3.2: json5 "^2.2.0" lazy-val "^1.0.4" -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -6384,11 +6431,27 @@ source-map@^0.7.4: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== +split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== +ssh2@^1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.15.0.tgz#2f998455036a7f89e0df5847efb5421748d9871b" + integrity sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.9" + nan "^2.18.0" + sshpk@^1.7.0: version "1.18.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" @@ -6584,6 +6647,16 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + tar-stream@3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.6.tgz#6520607b55a06f4a2e2e04db360ba7d338cc5bab" @@ -6593,7 +6666,7 @@ tar-stream@3.1.6: fast-fifo "^1.2.0" streamx "^2.15.0" -tar-stream@^2.1.0: +tar-stream@^2.0.0, tar-stream@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==