parent
e42a392286
commit
e9c806d750
@ -0,0 +1,4 @@ |
||||
#!/usr/bin/env sh |
||||
. "$(dirname -- "$0")/_/husky.sh" |
||||
|
||||
|
@ -0,0 +1,13 @@ |
||||
**/.yarn/* |
||||
|
||||
# Ignore node_modules |
||||
./node_modules |
||||
|
||||
# Ignore e2e files |
||||
./apps/remix-ide-e2e/* |
||||
|
||||
# Ignore build artefacts |
||||
./dist |
||||
|
||||
# Ignore all json files |
||||
**/*.json |
@ -0,0 +1,7 @@ |
||||
{ |
||||
"tabWidth": 2, |
||||
"useTabs": false, |
||||
"printWidth": 180, |
||||
"semi": false, |
||||
"singleQuote": true |
||||
} |
@ -0,0 +1,59 @@ |
||||
{ |
||||
"name": "circuit-compiler", |
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json", |
||||
"sourceRoot": "apps/circuit-compiler/src", |
||||
"projectType": "application", |
||||
"implicitDependencies": ["remixd"], |
||||
"targets": { |
||||
"build": { |
||||
"executor": "@nrwl/webpack:webpack", |
||||
"outputs": ["{options.outputPath}"], |
||||
"defaultConfiguration": "development", |
||||
"options": { |
||||
"compiler": "babel", |
||||
"outputPath": "dist/apps/circuit-compiler", |
||||
"index": "apps/circuit-compiler/src/index.html", |
||||
"baseHref": "./", |
||||
"main": "apps/circuit-compiler/src/main.tsx", |
||||
"polyfills": "apps/circuit-compiler/src/polyfills.ts", |
||||
"tsConfig": "apps/circuit-compiler/tsconfig.app.json", |
||||
"assets": ["apps/circuit-compiler/src/profile.json"], |
||||
"styles": ["apps/circuit-compiler/src/css/app.css"], |
||||
"scripts": [], |
||||
"webpackConfig": "apps/circuit-compiler/webpack.config.js" |
||||
}, |
||||
"configurations": { |
||||
"development": { |
||||
}, |
||||
"production": { |
||||
"fileReplacements": [ |
||||
{ |
||||
"replace": "apps/circuit-compiler/src/environments/environment.ts", |
||||
"with": "apps/circuit-compiler/src/environments/environment.prod.ts" |
||||
} |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
"serve": { |
||||
"executor": "@nrwl/webpack:dev-server", |
||||
"defaultConfiguration": "development", |
||||
"options": { |
||||
"buildTarget": "circuit-compiler:build", |
||||
"hmr": true, |
||||
"baseHref": "/" |
||||
}, |
||||
"configurations": { |
||||
"development": { |
||||
"buildTarget": "circuit-compiler:build:development", |
||||
"port": 2023 |
||||
}, |
||||
"production": { |
||||
"buildTarget": "circuit-compiler:build:production" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"tags": [] |
||||
} |
||||
|
@ -0,0 +1,17 @@ |
||||
import React, { useEffect } from 'react' |
||||
|
||||
import { CircomPluginClient } from './services/circomPluginClient' |
||||
|
||||
function App() { |
||||
|
||||
useEffect(() => { |
||||
new CircomPluginClient() |
||||
}, []) |
||||
|
||||
return ( |
||||
<div className="App"> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default App |
@ -0,0 +1,224 @@ |
||||
import {PluginClient} from '@remixproject/plugin' |
||||
import {createClient} from '@remixproject/plugin-webview' |
||||
import EventManager from 'events' |
||||
import pathModule from 'path' |
||||
import {parse} from 'circom_wasm' |
||||
|
||||
export class CircomPluginClient extends PluginClient { |
||||
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 |
||||
} |
||||
|
||||
buildFiles = await this.resolveDependencies(path, fileContent, buildFiles) |
||||
const parsedOutput = parse(path, buildFiles) |
||||
|
||||
try { |
||||
const result = JSON.parse(parsedOutput) |
||||
|
||||
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) { |
||||
if (report.labels[label].file_id === '0') { |
||||
// @ts-ignore
|
||||
const startPosition: {lineNumber: number; column: number} = |
||||
await this.call( |
||||
'editor', |
||||
// @ts-ignore
|
||||
'getPositionAt', |
||||
report.labels[label].range.start |
||||
) |
||||
// @ts-ignore
|
||||
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 |
||||
} |
||||
}, |
||||
file: path |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (markers.length > 0) { |
||||
// @ts-ignore
|
||||
await this.call('editor', 'addErrorMarker', markers) |
||||
} else { |
||||
// @ts-ignore
|
||||
await this.call('editor', 'clearErrorMarkers', [path]) |
||||
} |
||||
} |
||||
} catch (e) { |
||||
console.log(e) |
||||
} |
||||
} |
||||
|
||||
async resolveDependencies( |
||||
filePath: string, |
||||
fileContent: string, |
||||
output = {}, |
||||
depPath: string = '', |
||||
blackPath: string[] = [] |
||||
): Promise<Record<string, string>> { |
||||
// extract all includes
|
||||
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) { |
||||
// fetch file content if include import (path) exists within same level as current file opened in editor
|
||||
dependencyContent = await this.call('fileManager', 'readFile', path) |
||||
} else { |
||||
// if include import (path) does not exist, try to construct relative path using the original file path (current file opened in editor)
|
||||
let relativePath = pathModule.resolve( |
||||
filePath.slice(0, filePath.lastIndexOf('/')), |
||||
include |
||||
) |
||||
if (relativePath.indexOf('/') === 0) |
||||
relativePath = relativePath.slice(1) |
||||
const relativePathExists = await this.call( |
||||
'fileManager', |
||||
// @ts-ignore
|
||||
'exists', |
||||
relativePath |
||||
) |
||||
|
||||
if (relativePathExists) { |
||||
// fetch file content if include import exists as a relative path
|
||||
dependencyContent = await this.call( |
||||
'fileManager', |
||||
'readFile', |
||||
relativePath |
||||
) |
||||
} else { |
||||
if (depPath) { |
||||
// if depPath is provided, try to resolve include import from './deps' folder in remix
|
||||
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')) { |
||||
// try to resolve include import from github if it is a circomlib dependency
|
||||
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 { |
||||
// If all import cases are not true, use the default import to try fetching from node_modules and unpkg
|
||||
dependencyContent = await this.call( |
||||
'contentImport', |
||||
'resolveAndSave', |
||||
path, |
||||
null |
||||
) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
// extract all includes from the dependency content
|
||||
const dependencyIncludes = ( |
||||
dependencyContent.match(/include ['"].*['"]/g) || [] |
||||
).map((include) => |
||||
include.replace(/include ['"]/g, '').replace(/['"]/g, '') |
||||
) |
||||
|
||||
blackPath.push(include) |
||||
// recursively resolve all dependencies of the dependency
|
||||
if (dependencyIncludes.length > 0) { |
||||
await this.resolveDependencies( |
||||
filePath, |
||||
dependencyContent, |
||||
output, |
||||
path, |
||||
blackPath |
||||
) |
||||
output[include] = dependencyContent |
||||
} else { |
||||
output[include] = dependencyContent |
||||
} |
||||
}) |
||||
) |
||||
return output |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
pragma circom 2.0.0; |
||||
|
||||
template Multiplier2() { |
||||
signal input a; |
||||
signal input b; |
||||
signal output c; |
||||
c <== a*b; |
||||
} |
||||
|
||||
component main = Multiplier2(); |
||||
|
@ -0,0 +1,15 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8" /> |
||||
<title>Circuit - Compiler</title> |
||||
<base href="./" /> |
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"/> |
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> |
||||
</head> |
||||
<body> |
||||
<div id="root"></div> |
||||
</body> |
||||
</html> |
@ -0,0 +1,8 @@ |
||||
import React from 'react' |
||||
import ReactDOM from 'react-dom' |
||||
import App from './app/app' |
||||
|
||||
ReactDOM.render( |
||||
<App />, |
||||
document.getElementById('root') |
||||
) |
@ -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'; |
@ -0,0 +1,17 @@ |
||||
{ |
||||
"name": "circuit-compiler", |
||||
"kind": "provider", |
||||
"displayName": "Circuit Compiler", |
||||
"events": [], |
||||
"version": "2.0.0", |
||||
"methods": ["init", "parse"], |
||||
"canActivate": [], |
||||
"url": "", |
||||
"description": "Enables circuit compilation and computing a witness for ZK proofs", |
||||
"icon": "https://docs.circom.io/assets/images/favicon.png", |
||||
"location": "hiddenPanel", |
||||
"documentation": "", |
||||
"repo": "https://github.com/ethereum/remix-project/tree/master/apps/circuit-compiler", |
||||
"maintainedBy": "Remix", |
||||
"authorContact": "" |
||||
} |
@ -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"] |
||||
} |
||||
|
@ -0,0 +1,17 @@ |
||||
{ |
||||
"extends": "../../tsconfig.base.json", |
||||
"compilerOptions": { |
||||
"jsx": "react-jsx", |
||||
"allowJs": true, |
||||
"esModuleInterop": true, |
||||
"allowSyntheticDefaultImports": true |
||||
}, |
||||
"files": [], |
||||
"include": [], |
||||
"references": [ |
||||
{ |
||||
"path": "./tsconfig.app.json" |
||||
} |
||||
] |
||||
} |
||||
|
@ -0,0 +1,92 @@ |
||||
const { composePlugins, withNx } = require('@nrwl/webpack') |
||||
const webpack = require('webpack') |
||||
const TerserPlugin = require("terser-webpack-plugin") |
||||
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin") |
||||
|
||||
// Nx plugins for webpack.
|
||||
module.exports = composePlugins(withNx(), (config) => { |
||||
// Update the webpack config as needed here.
|
||||
// e.g. `config.plugins.push(new MyPlugin())`
|
||||
// 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), |
||||
}) |
||||
) |
||||
|
||||
// souce-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 |
||||
|
||||
return config; |
||||
}); |
@ -1,9 +1,6 @@ |
||||
import React from 'react'; |
||||
import ReactDOM from 'react-dom'; |
||||
import React from 'react' |
||||
import ReactDOM from 'react-dom' |
||||
|
||||
import App from './app/app'; |
||||
import App from './app/app' |
||||
|
||||
ReactDOM.render( |
||||
<App />, |
||||
document.getElementById('root') |
||||
); |
||||
ReactDOM.render(<App />, document.getElementById('root')) |
||||
|
@ -1,31 +1,28 @@ |
||||
import React from "react"; |
||||
import React from 'react' |
||||
|
||||
export const ErrorView: React.FC = () => { |
||||
return ( |
||||
<div |
||||
style={{ |
||||
width: "100%", |
||||
display: "flex", |
||||
flexDirection: "column", |
||||
alignItems: "center", |
||||
width: '100%', |
||||
display: 'flex', |
||||
flexDirection: 'column', |
||||
alignItems: 'center', |
||||
}} |
||||
> |
||||
<img |
||||
style={{ paddingBottom: "2em" }} |
||||
style={{ paddingBottom: '2em' }} |
||||
width="250" |
||||
src="https://res.cloudinary.com/key-solutions/image/upload/v1580400635/solid/error-png.png" |
||||
alt="Error page" |
||||
/> |
||||
<h5>Sorry, something unexpected happened. </h5> |
||||
<h5> |
||||
Please raise an issue:{" "} |
||||
<a |
||||
style={{ color: "red" }} |
||||
href="https://github.com/Machinalabs/remix-ethdoc-plugin/issues" |
||||
> |
||||
Please raise an issue:{' '} |
||||
<a style={{ color: 'red' }} href="https://github.com/Machinalabs/remix-ethdoc-plugin/issues"> |
||||
Here |
||||
</a> |
||||
</h5> |
||||
</div> |
||||
); |
||||
}; |
||||
) |
||||
} |
||||
|
@ -1,11 +1,11 @@ |
||||
import React from "react"; |
||||
import ReactDOM from "react-dom"; |
||||
import App from "./app/App"; |
||||
import React from 'react' |
||||
import ReactDOM from 'react-dom' |
||||
import App from './app/App' |
||||
// import { Routes } from "./routes";
|
||||
|
||||
ReactDOM.render( |
||||
<React.StrictMode> |
||||
<App /> |
||||
</React.StrictMode>, |
||||
document.getElementById("root") |
||||
); |
||||
document.getElementById('root'), |
||||
) |
||||
|
@ -1,24 +1,24 @@ |
||||
import React from "react" |
||||
import { PluginClient } from "@remixproject/plugin" |
||||
import React from 'react' |
||||
import {PluginClient} from '@remixproject/plugin' |
||||
|
||||
import { Receipt, ThemeType } from "./types" |
||||
import {Receipt, ThemeType} from './types' |
||||
|
||||
export const AppContext = React.createContext({ |
||||
apiKey: "", |
||||
apiKey: '', |
||||
setAPIKey: (value: string) => { |
||||
console.log("Set API Key from Context") |
||||
console.log('Set API Key from Context') |
||||
}, |
||||
clientInstance: {} as PluginClient, |
||||
receipts: [] as Receipt[], |
||||
setReceipts: (receipts: Receipt[]) => { |
||||
console.log("Calling Set Receipts") |
||||
console.log('Calling Set Receipts') |
||||
}, |
||||
contracts: [] as string[], |
||||
setContracts: (contracts: string[]) => { |
||||
console.log("Calling Set Contract Names") |
||||
console.log('Calling Set Contract Names') |
||||
}, |
||||
themeType: "dark" as ThemeType, |
||||
themeType: 'dark' as ThemeType, |
||||
setThemeType: (themeType: ThemeType) => { |
||||
console.log("Calling Set Theme Type") |
||||
}, |
||||
console.log('Calling Set Theme Type') |
||||
} |
||||
}) |
||||
|
@ -1,36 +1,38 @@ |
||||
export const scanAPIurls = { |
||||
// all mainnet
|
||||
1: "https://api.etherscan.io/api", |
||||
56: "https://api.bscscan.com/api", |
||||
137: "https://api.polygonscan.com/api", |
||||
250: "https://api.ftmscan.com/api", |
||||
42161: "https://api.arbiscan.io/api", |
||||
43114: "https://api.snowtrace.io/api", |
||||
1285: "https://api-moonriver.moonscan.io/api", |
||||
1284: "https://api-moonbeam.moonscan.io/api", |
||||
25: "https://api.cronoscan.com/api", |
||||
199: "https://api.bttcscan.com/api", |
||||
10: "https://api-optimistic.etherscan.io/api", |
||||
42220: "https://api.celoscan.io/api", |
||||
288: "https://api.bobascan.com/api", |
||||
100: "https://api.gnosisscan.io/api", |
||||
1101: "https://api-zkevm.polygonscan.com/api", |
||||
1: 'https://api.etherscan.io/api', |
||||
56: 'https://api.bscscan.com/api', |
||||
137: 'https://api.polygonscan.com/api', |
||||
250: 'https://api.ftmscan.com/api', |
||||
42161: 'https://api.arbiscan.io/api', |
||||
43114: 'https://api.snowtrace.io/api', |
||||
1285: 'https://api-moonriver.moonscan.io/api', |
||||
1284: 'https://api-moonbeam.moonscan.io/api', |
||||
25: 'https://api.cronoscan.com/api', |
||||
199: 'https://api.bttcscan.com/api', |
||||
10: 'https://api-optimistic.etherscan.io/api', |
||||
42220: 'https://api.celoscan.io/api', |
||||
288: 'https://api.bobascan.com/api', |
||||
100: 'https://api.gnosisscan.io/api', |
||||
1101: 'https://api-zkevm.polygonscan.com/api', |
||||
59144: 'https://api.lineascan.build/api', |
||||
|
||||
// all testnet
|
||||
5: "https://api-goerli.etherscan.io/api", |
||||
11155111: "https://api-sepolia.etherscan.io/api", |
||||
97: "https://api-testnet.bscscan.com/api", |
||||
80001: "https://api-testnet.polygonscan.com/api", |
||||
4002: "https://api-testnet.ftmscan.com/api", |
||||
421611: "https://api-testnet.arbiscan.io/api", |
||||
42170: "https://api-nova.arbiscan.io/api", |
||||
43113: "https://api-testnet.snowtrace.io/api", |
||||
1287: "https://api-moonbase.moonscan.io/api", |
||||
338: "https://api-testnet.cronoscan.com/api", |
||||
1028: "https://api-testnet.bttcscan.com/api", |
||||
420: "https://api-goerli-optimistic.etherscan.io/api", |
||||
44787: "https://api-alfajores.celoscan.io/api", |
||||
2888: "https://api-testnet.bobascan.com/api", |
||||
84531: "https://api-goerli.basescan.org/api", |
||||
1442: "https://api-testnet-zkevm.polygonscan.com/api" |
||||
5: 'https://api-goerli.etherscan.io/api', |
||||
11155111: 'https://api-sepolia.etherscan.io/api', |
||||
97: 'https://api-testnet.bscscan.com/api', |
||||
80001: 'https://api-testnet.polygonscan.com/api', |
||||
4002: 'https://api-testnet.ftmscan.com/api', |
||||
421611: 'https://api-testnet.arbiscan.io/api', |
||||
42170: 'https://api-nova.arbiscan.io/api', |
||||
43113: 'https://api-testnet.snowtrace.io/api', |
||||
1287: 'https://api-moonbase.moonscan.io/api', |
||||
338: 'https://api-testnet.cronoscan.com/api', |
||||
1028: 'https://api-testnet.bttcscan.com/api', |
||||
420: 'https://api-goerli-optimistic.etherscan.io/api', |
||||
44787: 'https://api-alfajores.celoscan.io/api', |
||||
2888: 'https://api-testnet.bobascan.com/api', |
||||
84531: 'https://api-goerli.basescan.org/api', |
||||
1442: 'https://api-testnet-zkevm.polygonscan.com/api', |
||||
59140: 'https://api-testnet.lineascan.build/api', |
||||
} |
@ -1,7 +1,11 @@ |
||||
import { StrictMode } from 'react'; |
||||
import * as ReactDOM from 'react-dom'; |
||||
import {StrictMode} from 'react' |
||||
import * as ReactDOM from 'react-dom' |
||||
|
||||
import App from './app/app' |
||||
|
||||
import App from './app/app'; |
||||
|
||||
ReactDOM.render(<StrictMode><App /></StrictMode>, document.getElementById('root')); |
||||
ReactDOM.render( |
||||
<StrictMode> |
||||
<App /> |
||||
</StrictMode>, |
||||
document.getElementById('root') |
||||
) |
||||
|
@ -1,9 +1,13 @@ |
||||
import React from 'react' |
||||
interface loggerProps { |
||||
log: any, |
||||
log: any |
||||
id: string |
||||
} |
||||
|
||||
export const Logger: React.FC<loggerProps> = (props) => { |
||||
return (<div id={props.id} className="jumbotron overflow-auto text-break mb-1 p-2">{props.log}</div>) |
||||
return ( |
||||
<div id={props.id} className="jumbotron overflow-auto text-break mb-1 p-2"> |
||||
{props.log} |
||||
</div> |
||||
) |
||||
} |
||||
|
@ -0,0 +1,345 @@ |
||||
'use strict' |
||||
import { NightwatchBrowser } from 'nightwatch' |
||||
import init from '../helpers/init' |
||||
|
||||
let firstProxyAddress: string |
||||
let lastProxyAddress: string |
||||
let shortenedFirstAddress: string |
||||
let shortenedLastAddress: string |
||||
module.exports = { |
||||
'@disabled': true, |
||||
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
||||
init(browser, done) |
||||
}, |
||||
|
||||
'@sources': function () { |
||||
return sources |
||||
}, |
||||
|
||||
'Should set the compiler version to 8.19': function(browser: NightwatchBrowser) { |
||||
browser.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') |
||||
}, |
||||
|
||||
'Should show deploy proxy option for UUPS upgradeable contract #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.addFile('myTokenV1.sol', sources[0]['myTokenV1.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.pause(2000) |
||||
// because the compilatiom imports are slow and sometimes stop loading (not sure why, it's bug) we need to recompile and check to see if the files are really in de FS
|
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.isVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable@4.8.3/proxy/beacon/IBeaconUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
suppressNotFoundErrors: true |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.isVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable@4.8.3/proxy/beacon/IBeaconUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
suppressNotFoundErrors: true |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.waitForElementVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable@4.8.3/proxy/beacon/IBeaconUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyToken]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
}, |
||||
|
||||
'Should show upgrade proxy option for child contract inheriting UUPS parent contract #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.addFile('myTokenV2.sol', sources[1]['myTokenV2.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
}, |
||||
|
||||
'Should deploy proxy without initialize parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.openFile('myTokenV1.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyToken]') |
||||
.verify.visible('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.click('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Deploy Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deploying ERC1967 < 5.0.0 as proxy...', 60000) |
||||
}, |
||||
|
||||
'Should interact with deployed contract via ERC1967 (proxy) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.getAddressAtPosition(1, (address) => { |
||||
firstProxyAddress = address |
||||
shortenedFirstAddress = address.slice(0, 5) + '...' + address.slice(address.length - 5, address.length) |
||||
}) |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'name - call', null, '0:\nstring: MyToken').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'symbol - call', null, '0:\nstring: MTK').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should deploy proxy with initialize parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.addFile('initializeProxy.sol', sources[2]['initializeProxy.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyInitializedToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyInitializedToken]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.click('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.useXpath() |
||||
.waitForElementPresent('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[1]/input') |
||||
.waitForElementPresent('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/input') |
||||
.setValue('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[1]/input', 'Remix') |
||||
.setValue('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/input', "R") |
||||
.useCss() |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Deploy Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deploying ERC1967 < 5.0.0 as proxy...', 60000) |
||||
}, |
||||
|
||||
'Should interact with initialized contract to verify parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.getAddressAtPosition(1, (address) => { |
||||
lastProxyAddress = address |
||||
shortenedLastAddress = address.slice(0, 5) + '...' + address.slice(address.length - 5, address.length) |
||||
}) |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'name - call', null, '0:\nstring: Remix').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'symbol - call', null, '0:\nstring: R').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should upgrade contract by selecting a previously deployed proxy address from dropdown (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.click('*[data-id="terminalClearConsole"]')
|
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.openFile('myTokenV2.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.click('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.waitForElementPresent('[data-id="toggleProxyAddressDropdown"]') |
||||
.click('[data-id="toggleProxyAddressDropdown"]') |
||||
.waitForElementVisible('[data-id="proxy-dropdown-items"]') |
||||
.assert.textContains('[data-id="proxy-dropdown-items"]', shortenedFirstAddress) |
||||
.assert.textContains('[data-id="proxy-dropdown-items"]', shortenedLastAddress) |
||||
.click('[data-id="proxyAddress1"]') |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Update Proxy') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click( |
||||
{ |
||||
selector: '[data-id="confirmProxyDeployment-modal-footer-ok-react"]', |
||||
}) |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Using ERC1967 < 5.0.0 for the proxy upgrade..', 60000) |
||||
}, |
||||
|
||||
'Should interact with upgraded function in contract MyTokenV2 #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'version - call', null, '0:\nstring: MyTokenV2!').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should upgrade contract by providing proxy address in input field (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.click('*[data-id="terminalClearConsole"]')
|
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.openFile('myTokenV2.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.waitForElementPresent('[data-id="toggleProxyAddressDropdown"]') |
||||
.clearValue('[data-id="ERC1967AddressInput"]') |
||||
.setValue('[data-id="ERC1967AddressInput"]', firstProxyAddress) |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Update Proxy') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Using ERC1967 < 5.0.0 for the proxy upgrade..', 60000) |
||||
}, |
||||
|
||||
'Should interact with upgraded contract through provided proxy address #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.clearConsole() |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'version - call', null, '0:\nstring: MyTokenV2!').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
'Should debug the call': function(browser: NightwatchBrowser) { |
||||
browser |
||||
.debugTransaction(0) |
||||
.waitForElementVisible({ |
||||
locateStrategy: 'xpath', |
||||
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"11")]', |
||||
timeout: 60000 |
||||
}) |
||||
.goToVMTraceStep(146) |
||||
.waitForElementContainsText('*[data-id="functionPanel"]', 'version()', 60000)
|
||||
.end() |
||||
} |
||||
} |
||||
|
||||
|
||||
const sources = [ |
||||
{ |
||||
'myTokenV1.sol': { |
||||
content: ` |
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.4; |
||||
|
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/token/ERC721/ERC721Upgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/access/OwnableUpgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/Initializable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/UUPSUpgradeable.sol"; |
||||
|
||||
contract MyToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable { |
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor() { |
||||
_disableInitializers(); |
||||
} |
||||
|
||||
function initialize() initializer public { |
||||
__ERC721_init("MyToken", "MTK"); |
||||
__Ownable_init(); |
||||
__UUPSUpgradeable_init(); |
||||
} |
||||
|
||||
function _authorizeUpgrade(address newImplementation) |
||||
internal |
||||
onlyOwner |
||||
override |
||||
{} |
||||
} |
||||
` |
||||
} |
||||
}, { |
||||
'myTokenV2.sol': { |
||||
content: ` |
||||
import "./myTokenV1.sol"; |
||||
|
||||
contract MyTokenV2 is MyToken { |
||||
function version () public view returns (string memory) { |
||||
return "MyTokenV2!"; |
||||
} |
||||
} |
||||
` |
||||
} |
||||
}, { |
||||
'initializeProxy.sol': { |
||||
content: ` |
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.4; |
||||
|
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/token/ERC721/ERC721Upgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/access/OwnableUpgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/Initializable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/UUPSUpgradeable.sol"; |
||||
|
||||
contract MyInitializedToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable { |
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor() { |
||||
_disableInitializers(); |
||||
} |
||||
|
||||
function initialize(string memory tokenName, string memory tokenSymbol) initializer public { |
||||
__ERC721_init(tokenName, tokenSymbol); |
||||
__Ownable_init(); |
||||
__UUPSUpgradeable_init(); |
||||
} |
||||
|
||||
function _authorizeUpgrade(address newImplementation) |
||||
internal |
||||
onlyOwner |
||||
override |
||||
{} |
||||
} |
||||
` |
||||
} |
||||
} |
||||
] |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,47 @@ |
||||
import { Plugin } from '@remixproject/engine' |
||||
import { CreateChatCompletionResponse } from 'openai' |
||||
|
||||
const _paq = (window._paq = window._paq || []) |
||||
|
||||
const profile = { |
||||
name: 'openaigpt', |
||||
displayName: 'openaigpt', |
||||
description: 'openaigpt', |
||||
methods: ['message'], |
||||
events: [], |
||||
maintainedBy: 'Remix', |
||||
} |
||||
|
||||
export class OpenAIGpt extends Plugin { |
||||
constructor() { |
||||
super(profile) |
||||
} |
||||
|
||||
async message(prompt): Promise<CreateChatCompletionResponse> { |
||||
this.call('layout', 'maximizeTerminal') |
||||
this.call('terminal', 'log', 'Waiting for GPT answer...') |
||||
let result |
||||
try { |
||||
result = await ( |
||||
await fetch('https://openai-gpt.remixproject.org', { |
||||
method: 'POST', |
||||
headers: { |
||||
Accept: 'application/json', |
||||
'Content-Type': 'application/json', |
||||
}, |
||||
body: JSON.stringify({ prompt }), |
||||
}) |
||||
).json() |
||||
} catch (e) { |
||||
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` }) |
||||
return |
||||
} |
||||
|
||||
if (result && result.choices && result.choices.length) { |
||||
this.call('terminal', 'log', { type: 'typewritersuccess', value: result.choices[0].message.content })
|
||||
} else { |
||||
this.call('terminal', 'log', { type: 'typewritersuccess', value: 'No response...' }) |
||||
} |
||||
return result.data |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue