Skip to content

Commit e20ad42

Browse files
authored
Merge pull request #36 from quantanet/deploy
Deploy compiled contracts
2 parents 068a2ba + 39b8dcb commit e20ad42

File tree

19 files changed

+1806
-1268
lines changed

19 files changed

+1806
-1268
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
],
1616
"stopOnEntry": false,
1717
"sourceMaps": true,
18-
"outFiles": ["${workspaceRoot}/ext-src"],
18+
"outFiles": ["${workspaceRoot}/build/ext-src"],
1919
"preLaunchTask": "npm: watch"
2020
},
2121
{

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
**Note:** *compilation with latest/default version is faster. compilation with any other selected version can be slower as it loads the compiler version from internet.*
1919

20+
## Vyper support
21+
Please install vyper compiler for compiling vyper contracts in ethcode. Instructions for vyper compiler installation can be found on official vyper documentation - https://vyper.readthedocs.io/en/latest/installing-vyper.html
22+
2023
## Help
2124
Please help ethcode developers continue their work.
2225

ext-src/extension.ts

Lines changed: 158 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,14 @@ class ReactPanel {
110110
// Handle messages from the webview
111111
this._panel.webview.onDidReceiveMessage(
112112
(message: any) => {
113-
switch (message.command) {
114-
case "version":
115-
this.version = message.version;
116-
case "debugTransaction":
117-
this.debug(message.txHash);
113+
if(message.command === 'version') {
114+
this.version = message.version;
115+
} else if(message.command === 'run-deploy') {
116+
this.runDeploy(message.payload);
117+
} else if(message.command === 'run-get-gas-estimate') {
118+
this.runGetGasEstimate(message.payload);
119+
} else if(message.command === 'debugTransaction') {
120+
this.debug(message.txHash);
118121
}
119122
},
120123
null,
@@ -123,10 +126,107 @@ class ReactPanel {
123126
}
124127

125128
private createWorker(): ChildProcess {
126-
return fork(path.join(__dirname, "worker.js"), [], {
127-
execArgv: ["--inspect=" + (process.debugPort + 1)]
128-
});
129+
// enable --inspect for debug
130+
// return fork(path.join(__dirname, "worker.js"), [], {
131+
// execArgv: ["--inspect=" + (process.debugPort + 1)]
132+
// });
133+
return fork(path.join(__dirname, "worker.js"));
134+
}
135+
private createVyperWorker(): ChildProcess {
136+
// enable --inspect for debug
137+
// return fork(path.join(__dirname, "vyp-worker.js"), [], {
138+
// execArgv: ["--inspect=" + (process.debugPort + 1)]
139+
// });
140+
return fork(path.join(__dirname, "vyp-worker.js"));
129141
}
142+
private invokeSolidityCompiler(context: vscode.ExtensionContext, sources: ISources): void {
143+
// solidity compiler code goes bellow
144+
var input = {
145+
language: "Solidity",
146+
sources,
147+
settings: {
148+
outputSelection: {
149+
"*": {
150+
"*": ["*"]
151+
}
152+
}
153+
}
154+
};
155+
// child_process won't work because of debugging issue if launched with F5
156+
// child_process will work when launched with ctrl+F5
157+
// more on this - https://github.com/Microsoft/vscode/issues/40875
158+
const solcWorker = this.createWorker();
159+
console.dir("WorkerID: ", solcWorker.pid);
160+
console.dir("Compiling with solidity version ", this.version);
161+
// Reset Components State before compilation
162+
this._panel.webview.postMessage({ processMessage: "Compiling..." });
163+
solcWorker.send({
164+
command: "compile",
165+
payload: input,
166+
version: this.version
167+
});
168+
solcWorker.on("message", (m: any) => {
169+
if (m.data && m.path) {
170+
sources[m.path] = {
171+
content: m.data.content
172+
};
173+
solcWorker.send({
174+
command: "compile",
175+
payload: input,
176+
version: this.version
177+
});
178+
}
179+
if (m.compiled) {
180+
// console.dir(m.compiled);
181+
// console.dir(JSON.stringify(sources));
182+
context.workspaceState.update("sources", JSON.stringify(sources));
183+
184+
this._panel.webview.postMessage({ compiled: m.compiled, sources });
185+
solcWorker.kill();
186+
}
187+
if (m.processMessage) {
188+
this._panel.webview.postMessage({ processMessage: m.processMessage });
189+
}
190+
});
191+
solcWorker.on("error", (error: Error) => {
192+
console.log(
193+
"%c Compile worker process exited with error" + `${error.message}`,
194+
"background: rgba(36, 194, 203, 0.3); color: #EF525B"
195+
);
196+
});
197+
solcWorker.on("exit", (code: number, signal: string) => {
198+
console.log(
199+
"%c Compile worker process exited with " +
200+
`code ${code} and signal ${signal}`,
201+
"background: rgba(36, 194, 203, 0.3); color: #EF525B"
202+
);
203+
this._panel.webview.postMessage({
204+
message: `Error code ${code} : Error signal ${signal}`
205+
});
206+
});
207+
}
208+
private invokeVyperCompiler(context: vscode.ExtensionContext, sources: ISources): void {
209+
const vyperWorker = this.createVyperWorker();
210+
console.dir("WorkerID: ", vyperWorker.pid);
211+
console.dir("Compiling with vyper compiler version ", this.version);
212+
this._panel.webview.postMessage({ processMessage: "Compiling..." });
213+
vyperWorker.send({
214+
command: "compile",
215+
source: sources,
216+
version: this.version
217+
});
218+
vyperWorker.on('message', (m) => {
219+
if (m.compiled) {
220+
context.workspaceState.update("sources", JSON.stringify(sources));
221+
222+
this._panel.webview.postMessage({ compiled: m.compiled, sources });
223+
vyperWorker.kill();
224+
}
225+
if (m.processMessage) {
226+
this._panel.webview.postMessage({ processMessage: m.processMessage });
227+
}
228+
});
229+
}
130230
private debug(txHash: string): void {
131231
const debugWorker = this.createWorker();
132232
console.dir("WorkerID: ", debugWorker.pid);
@@ -137,80 +237,61 @@ class ReactPanel {
137237
});
138238
debugWorker.send({ command: "debug-transaction", payload: txHash });
139239
}
140-
public sendCompiledContract(context: vscode.ExtensionContext, editorContent: string | undefined, fn: string | undefined) {
141-
// send JSON serializable compiled data
142-
const sources: ISources = {};
143-
if (fn) {
144-
sources[fn] = {
145-
content: editorContent
146-
};
147-
context.workspaceState.update("sources", JSON.stringify(sources));
148-
}
149-
var input = {
150-
language: "Solidity",
151-
sources,
152-
settings: {
153-
outputSelection: {
154-
"*": {
155-
"*": ["*"]
156-
}
157-
}
240+
// Deploy contracts
241+
private runDeploy(payload: any) {
242+
const deployWorker = this.createWorker();
243+
deployWorker.on("message", (m: any) => {
244+
console.log("Deploy message: ");
245+
console.dir(m);
246+
if(m.error) {
247+
this._panel.webview.postMessage({ errors: m.error });
158248
}
159-
};
160-
// child_process won't work because of debugging issue if launched with F5
161-
// child_process will work when launched with ctrl+F5
162-
// more on this - https://github.com/Microsoft/vscode/issues/40875
163-
const solcWorker = this.createWorker();
164-
console.dir("WorkerID: ", solcWorker.pid);
165-
console.dir("Compiling with solidity version ", this.version);
166-
167-
// Reset Components State before compilation
168-
this._panel.webview.postMessage({ processMessage: "Compiling..." });
169-
solcWorker.send({
170-
command: "compile",
171-
payload: input,
172-
version: this.version
173-
});
174-
solcWorker.on("message", (m: any) => {
175-
if (m.data && m.path) {
176-
sources[m.path] = {
177-
content: m.data.content
178-
};
179-
solcWorker.send({
180-
command: "compile",
181-
payload: input,
182-
version: this.version
183-
});
249+
else {
250+
this._panel.webview.postMessage({ deployedResult: m });
184251
}
185-
if (m.compiled) {
186-
// console.dir(m.compiled);
187-
// console.dir(JSON.stringify(sources));
188-
context.workspaceState.update("sources", JSON.stringify(sources));
252+
});
253+
deployWorker.send({ command: "deploy-contract", payload });
254+
}
255+
// Get gas estimates
256+
private runGetGasEstimate(payload: any) {
257+
const deployWorker = this.createWorker();
189258

190-
this._panel.webview.postMessage({ compiled: m.compiled, sources });
191-
solcWorker.kill();
259+
deployWorker.on("message", (m: any) => {
260+
if(m.error) {
261+
this._panel.webview.postMessage({ errors: m.error });
192262
}
193-
if (m.processMessage) {
194-
this._panel.webview.postMessage({ processMessage: m.processMessage });
263+
else {
264+
this._panel.webview.postMessage({ gasEstimate: m.gasEstimate });
195265
}
266+
console.log("Gas estimate message: ");
267+
console.dir(JSON.stringify(m));
196268
});
197-
solcWorker.on("error", (error: Error) => {
198-
console.log(
199-
"%c Compile worker process exited with error" + `${error.message}`,
200-
"background: rgba(36, 194, 203, 0.3); color: #EF525B"
201-
);
202-
});
203-
solcWorker.on("exit", (code: number, signal: string) => {
204-
console.log(
205-
"%c Compile worker process exited with " +
206-
`code ${code} and signal ${signal}`,
207-
"background: rgba(36, 194, 203, 0.3); color: #EF525B"
208-
);
209-
this._panel.webview.postMessage({
210-
message: `Error code ${code} : Error signal ${signal}`
211-
});
212-
});
269+
deployWorker.send({ command: "get-gas-estimate", payload });
213270
}
271+
public sendCompiledContract(context: vscode.ExtensionContext, editorContent: string | undefined, fn: string | undefined) {
272+
// send JSON serializable compiled data
273+
const sources: ISources = {};
274+
if (fn) {
275+
sources[fn] = {
276+
content: editorContent
277+
};
278+
context.workspaceState.update("sources", JSON.stringify(sources));
279+
var re = /(?:\.([^.]+))?$/;
280+
const regexVyp = /([a-zA-Z0-9\s_\\.\-\(\):])+(.vy|.v.py|.vyper.py)$/g;
281+
const regexSol = /([a-zA-Z0-9\s_\\.\-\(\):])+(.sol|.solidity)$/g;
282+
// @ts-ignore
283+
if (fn.match(regexVyp) && fn.match(regexVyp).length > 0) {
284+
// invoke vyper compiler
285+
this.invokeVyperCompiler(context, sources);
286+
// @ts-ignore
287+
} else if (fn.match(regexSol) && fn.match(regexSol).length > 0) {
288+
// invoke solidity compiler
289+
this.invokeSolidityCompiler(context, sources);
290+
} else {
291+
throw new Error("No matching file found!");
292+
}
293+
}
294+
}
214295

215296
public sendTestContract(editorContent: string | undefined, fn: string | undefined) {
216297
const sources: ISources = {};
@@ -249,6 +330,7 @@ class ReactPanel {
249330
console.dir("Tests worker exited");
250331
});
251332
}
333+
252334

253335
public dispose() {
254336
ReactPanel.currentPanel = undefined;
@@ -350,4 +432,4 @@ function getNonce() {
350432
text += possible.charAt(Math.floor(Math.random() * possible.length));
351433
}
352434
return text;
353-
}
435+
}

ext-src/vyp-worker.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// @ts-ignore
2+
import * as shell from "shelljs";
3+
import * as fs from "fs";
4+
import { ISources } from "./types";
5+
6+
function compileVyper(sources: ISources) {
7+
var input_json = {
8+
"language": "Vyper",
9+
"sources": sources,
10+
"settings": {
11+
"evmVersion": "byzantium"
12+
},
13+
"outputSelection": {
14+
"*": ["evm.bytecode", "abi", "ast"],
15+
}
16+
};
17+
shell.config.execPath = shell.which('node').toString();
18+
fs.writeFileSync(__dirname + "/" + ".temp-vy.json", JSON.stringify(input_json, null, 4), 'UTF-8');
19+
var args: string = "vyper-json " + __dirname + "/" + ".temp-vy.json";
20+
var escaped = shell.exec(args);
21+
var m: object = { "compiled": escaped }
22+
fs.unlink(__dirname + "/" + ".temp-vy.json", () => {});
23+
// @ts-ignore
24+
process.send(m);
25+
}
26+
27+
// @ts-ignore
28+
process.on('message', (m) => {
29+
if (m.command == "compile") {
30+
compileVyper(m.source);
31+
}
32+
})

0 commit comments

Comments
 (0)