parent
75b011964f
commit
e61ba8f808
@ -1,6 +0,0 @@ |
||||
import { Dispatch } from "react" |
||||
import { Action } from "../types" |
||||
|
||||
export const dispatchCheckRemixd = (status: boolean) => (dispatch: Dispatch<Action<'SET_REMIXD_CONNECTION_STATUS'>>) => { |
||||
dispatch({ type: 'SET_REMIXD_CONNECTION_STATUS', payload: status }) |
||||
} |
@ -1 +0,0 @@ |
||||
import { Dispatch } from 'react' |
@ -1,31 +1,16 @@ |
||||
import React, { useEffect, useReducer, useState } from 'react' |
||||
import { RenderIf, RenderIfNot } from '@remix-ui/helper' |
||||
import { Alert, Button, Tabs, Tab } from 'react-bootstrap' |
||||
import React, { useEffect } from 'react' |
||||
|
||||
import { AppContext } from './contexts' |
||||
import { appInitialState, appReducer } from './reducers' |
||||
import { CircomPluginClient } from './services/circomPluginClient' |
||||
|
||||
function App() { |
||||
const [appState, dispatch] = useReducer(appReducer, appInitialState) |
||||
const [plugin, setPlugin] = useState<CircomPluginClient>(null) |
||||
|
||||
useEffect(() => { |
||||
const plugin = new CircomPluginClient() |
||||
|
||||
setPlugin(plugin) |
||||
new CircomPluginClient() |
||||
}, []) |
||||
|
||||
const value = { |
||||
appState, |
||||
dispatch |
||||
} |
||||
|
||||
return ( |
||||
<AppContext.Provider value={value}> |
||||
<div className="App"> |
||||
</div> |
||||
</AppContext.Provider> |
||||
<div className="App"> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
|
@ -1,30 +0,0 @@ |
||||
// const compile = () => {
|
||||
// const currentFile = api.currentFile
|
||||
|
||||
// if (currentFile.endsWith('.circom')) return compileCircuit()
|
||||
// if (!isSolFileSelected()) return
|
||||
// _setCompilerVersionFromPragma(currentFile)
|
||||
// let externalCompType
|
||||
// if (hhCompilation) externalCompType = 'hardhat'
|
||||
// else if (truffleCompilation) externalCompType = 'truffle'
|
||||
// compileTabLogic.runCompiler(externalCompType)
|
||||
// }
|
||||
|
||||
// const compileAndRun = () => {
|
||||
// const currentFile = api.currentFile
|
||||
|
||||
// if (currentFile.endsWith('.circom')) return compileCircuit()
|
||||
// if (!isSolFileSelected()) return
|
||||
// _setCompilerVersionFromPragma(currentFile)
|
||||
// let externalCompType
|
||||
// if (hhCompilation) externalCompType = 'hardhat'
|
||||
// else if (truffleCompilation) externalCompType = 'truffle'
|
||||
// api.runScriptAfterCompilation(currentFile)
|
||||
// compileTabLogic.runCompiler(externalCompType)
|
||||
// }
|
||||
|
||||
// const compileCircuit = () => {
|
||||
// const currentFile = api.currentFile
|
||||
|
||||
// console.log('Compiling circuit ' + currentFile)
|
||||
// }
|
@ -1,4 +0,0 @@ |
||||
import { createContext } from 'react' |
||||
import { IAppContext } from '../types' |
||||
|
||||
export const AppContext = createContext<IAppContext>({} as IAppContext) |
@ -1,18 +0,0 @@ |
||||
import { Actions, AppState } from "../types" |
||||
|
||||
export const appInitialState: AppState = { |
||||
isRemixdConnected: null |
||||
} |
||||
|
||||
export const appReducer = (state = appInitialState, action: Actions): AppState => { |
||||
switch (action.type) { |
||||
case 'SET_REMIXD_CONNECTION_STATUS': |
||||
return { |
||||
...state, |
||||
isRemixdConnected: action.payload |
||||
} |
||||
|
||||
default: |
||||
throw new Error() |
||||
} |
||||
} |
@ -1,108 +1,137 @@ |
||||
import { PluginClient } from '@remixproject/plugin' |
||||
import { createClient } from '@remixproject/plugin-webview' |
||||
import { parse_circuit_browser, main_browser } from 'apps/circuit-compiler/pkg/circom' |
||||
import { generate_witness } from 'apps/circuit-compiler/pkg/generate_witness' |
||||
import EventManager from 'events' |
||||
|
||||
const pathModule = require('path') |
||||
import pathModule from 'path' |
||||
import { parse } from 'circom_wasm' |
||||
|
||||
export class CircomPluginClient extends PluginClient { |
||||
private connected: boolean |
||||
public internalEvents: EventManager |
||||
|
||||
constructor() { |
||||
super() |
||||
createClient(this) |
||||
this.internalEvents = new EventManager() |
||||
this.methods = ["init", "compile"] |
||||
this.onload() |
||||
} |
||||
|
||||
init (): void { |
||||
console.log('initializing circom plugin...') |
||||
public internalEvents: EventManager |
||||
|
||||
constructor() { |
||||
super() |
||||
createClient(this) |
||||
this.internalEvents = new EventManager() |
||||
this.methods = ["init", "parse"] |
||||
this.onload() |
||||
} |
||||
|
||||
init (): void { |
||||
console.log('initializing circom plugin...') |
||||
} |
||||
|
||||
onActivation(): void { |
||||
// @ts-ignore
|
||||
this.on('editor', 'contentChanged', (path: string, fileContent) => { |
||||
if (path.endsWith('.circom')) { |
||||
this.parse(path, fileContent) |
||||
} |
||||
}) |
||||
} |
||||
|
||||
async parse (path: string, fileContent: string): Promise<void> { |
||||
let buildFiles = { |
||||
[path]: fileContent |
||||
} |
||||
|
||||
async compile (path: string) { |
||||
const fileContent = await this.call('fileManager', 'readFile', path) |
||||
let buildFiles = { |
||||
[path]: fileContent |
||||
} |
||||
|
||||
buildFiles = await this.resolveDependencies(path, fileContent, buildFiles) |
||||
const compilationResult = main_browser(path, buildFiles, { prime: "bn128" }) |
||||
|
||||
console.log('compilation result: ' + compilationResult) |
||||
|
||||
generate_witness(compilationResult, '{ "a": "3", "b": "11" }') |
||||
generate_witness(compilationResult, '{ "a": "5", "b": "77" }') |
||||
} |
||||
|
||||
async parse (path: string) { |
||||
const fileContent = await this.call('fileManager', 'readFile', path) |
||||
let buildFiles = { |
||||
[path]: fileContent |
||||
} |
||||
|
||||
buildFiles = await this.resolveDependencies(path, fileContent, buildFiles) |
||||
const parsingResult = parse_circuit_browser(path, buildFiles, { prime: "bn128" }) |
||||
buildFiles = await this.resolveDependencies(path, fileContent, buildFiles) |
||||
const parsedOutput = parse(path, buildFiles) |
||||
|
||||
console.log('parsing result: ' + parsingResult) |
||||
} |
||||
|
||||
async resolveDependencies (filePath: string, fileContent: string, output = {}, depPath: string = '', blackPath: string[] = []) { |
||||
const includes = (fileContent.match(/include ['"].*['"]/g) || []).map(include => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
||||
try { |
||||
const result = JSON.parse(parsedOutput) |
||||
const markers = [] |
||||
|
||||
await Promise.all(includes.map(async include => { |
||||
// fix for endless recursive includes
|
||||
if (blackPath.includes(include)) return |
||||
let dependencyContent = '' |
||||
let path = include |
||||
for (const report of result) { |
||||
for (const label in report.labels) { |
||||
if (report.labels[label].file_id === '0') { |
||||
// @ts-ignore
|
||||
const pathExists = await this.call('fileManager', 'exists', path) |
||||
|
||||
if (pathExists) { |
||||
dependencyContent = await this.call('fileManager', 'readFile', path) |
||||
} else { |
||||
let relativePath = pathModule.resolve(filePath.slice(0, filePath.lastIndexOf('/')), include) |
||||
if (relativePath.indexOf('/') === 0) relativePath = relativePath.slice(1) |
||||
// @ts-ignore
|
||||
const relativePathExists = await this.call('fileManager', 'exists', relativePath) |
||||
|
||||
if (relativePathExists) { |
||||
dependencyContent = await this.call('fileManager', 'readFile', relativePath) |
||||
} else { |
||||
if (depPath) { |
||||
path = pathModule.resolve(depPath.slice(0, depPath.lastIndexOf('/')), include) |
||||
if (path.indexOf('/') === 0) path = path.slice(1) |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} else { |
||||
if (include.startsWith('circomlib')) { |
||||
const splitInclude = include.split('/') |
||||
const version = splitInclude[1].match(/v[0-9]+.[0-9]+.[0-9]+/g) |
||||
|
||||
if (version && version[0]) { |
||||
path = `https://raw.githubusercontent.com/iden3/circomlib/${version[0]}/circuits/${splitInclude.slice(2).join('/')}` |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} else { |
||||
path = `https://raw.githubusercontent.com/iden3/circomlib/master/circuits/${splitInclude.slice(1).join('/')}` |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} |
||||
} else { |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} |
||||
} |
||||
const startPosition: { lineNumber: number, column: number } = await this.call('editor', 'getPositionAt', report.labels[label].range.start) |
||||
// @ts-ignore
|
||||
const endPosition: { lineNumber: number, column: number } = await this.call('editor', 'getPositionAt', report.labels[label].range.end) |
||||
|
||||
|
||||
console.log('startPosition: ', startPosition) |
||||
console.log('endPosition: ', endPosition) |
||||
markers.push({ |
||||
message: report.message, |
||||
severity: report.type.toLowerCase(), |
||||
position: { |
||||
start: { |
||||
line: startPosition.lineNumber, |
||||
column: startPosition.column |
||||
}, |
||||
end: { |
||||
line: endPosition.lineNumber, |
||||
column: endPosition.column |
||||
} |
||||
} |
||||
const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map(include => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
||||
|
||||
blackPath.push(include) |
||||
if (dependencyIncludes.length > 0) { |
||||
await this.resolveDependencies(filePath, dependencyContent, output, path, blackPath) |
||||
output[include] = dependencyContent |
||||
}, |
||||
file: path |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
// @ts-ignore
|
||||
await this.call('editor', 'addErrorMarker', markers) |
||||
} catch (e) { |
||||
// @ts-ignore
|
||||
await this.call('editor', 'clearErrorMarkers', [path]) |
||||
console.log(parsedOutput) |
||||
} |
||||
} |
||||
|
||||
async resolveDependencies (filePath: string, fileContent: string, output = {}, depPath: string = '', blackPath: string[] = []): Promise<Record<string, string>> { |
||||
const includes = (fileContent.match(/include ['"].*['"]/g) || []).map(include => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
||||
|
||||
await Promise.all(includes.map(async include => { |
||||
// fix for endless recursive includes
|
||||
if (blackPath.includes(include)) return |
||||
let dependencyContent = '' |
||||
let path = include |
||||
// @ts-ignore
|
||||
const pathExists = await this.call('fileManager', 'exists', path) |
||||
|
||||
if (pathExists) { |
||||
dependencyContent = await this.call('fileManager', 'readFile', path) |
||||
} else { |
||||
let relativePath = pathModule.resolve(filePath.slice(0, filePath.lastIndexOf('/')), include) |
||||
if (relativePath.indexOf('/') === 0) relativePath = relativePath.slice(1) |
||||
// @ts-ignore
|
||||
const relativePathExists = await this.call('fileManager', 'exists', relativePath) |
||||
|
||||
if (relativePathExists) { |
||||
dependencyContent = await this.call('fileManager', 'readFile', relativePath) |
||||
} else { |
||||
if (depPath) { |
||||
path = pathModule.resolve(depPath.slice(0, depPath.lastIndexOf('/')), include) |
||||
if (path.indexOf('/') === 0) path = path.slice(1) |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} else { |
||||
if (include.startsWith('circomlib')) { |
||||
const splitInclude = include.split('/') |
||||
const version = splitInclude[1].match(/v[0-9]+.[0-9]+.[0-9]+/g) |
||||
|
||||
if (version && version[0]) { |
||||
path = `https://raw.githubusercontent.com/iden3/circomlib/${version[0]}/circuits/${splitInclude.slice(2).join('/')}` |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} else { |
||||
path = `https://raw.githubusercontent.com/iden3/circomlib/master/circuits/${splitInclude.slice(1).join('/')}` |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} |
||||
} else { |
||||
output[include] = dependencyContent |
||||
dependencyContent = await this.call('contentImport', 'resolveAndSave', path, null) |
||||
} |
||||
})) |
||||
return output |
||||
} |
||||
} |
||||
} |
||||
} |
||||
const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map(include => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) |
||||
|
||||
blackPath.push(include) |
||||
if (dependencyIncludes.length > 0) { |
||||
await this.resolveDependencies(filePath, dependencyContent, output, path, blackPath) |
||||
output[include] = dependencyContent |
||||
} else { |
||||
output[include] = dependencyContent |
||||
} |
||||
})) |
||||
return output |
||||
} |
||||
} |
||||
|
@ -1,22 +0,0 @@ |
||||
import { Dispatch } from "react" |
||||
|
||||
export interface IAppContext { |
||||
appState: AppState, |
||||
dispatch: Dispatch<any> |
||||
} |
||||
|
||||
export interface ActionPayloadTypes { |
||||
SET_REMIXD_CONNECTION_STATUS: boolean |
||||
} |
||||
|
||||
|
||||
export interface Action <T extends keyof ActionPayloadTypes> { |
||||
type: T |
||||
payload: ActionPayloadTypes[T] |
||||
} |
||||
|
||||
export type Actions = { [A in keyof ActionPayloadTypes]: Action<A> }[keyof ActionPayloadTypes] |
||||
|
||||
export interface AppState { |
||||
isRemixdConnected: boolean |
||||
} |
Before Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in new issue