Skip to content

Commit 84c8b5e

Browse files
authored
Merge pull request #13 from OpenZeppelin/main
Release to wizard
2 parents e87118a + fb6ffbe commit 84c8b5e

File tree

13 files changed

+215
-12
lines changed

13 files changed

+215
-12
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@remixproject/plugin-utils": "^0.3.38",
2727
"@sveltejs/adapter-netlify": "^4.3.6",
2828
"bootstrap": "^5.3.3",
29-
"ethers": "^6.13.4"
29+
"ethers": "^6.13.4",
30+
"solc": "^0.8.28"
3031
}
3132
}

pnpm-lock.yaml

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ declare global {
1313
declare interface Window {
1414
ethereum?: import('ethers').Eip1193Provider & import('ethers').BrowserProvider;
1515
}
16+
17+
// solc does not have a type definition file.
18+
declare module 'solc' {
19+
export function compile(input: string, opts?: any): any;
20+
}

src/lib/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { CreateApprovalProcessRequest } from "./models/approval-process";
22
import type { Credentials } from "./models/auth";
33
import type { DeployContractRequest, UpdateDeploymentRequest } from "./models/deploy";
4+
import type { CompilerInput } from "./models/solc";
45

56
class ApiClient {
67
credentials: Credentials | null = null;
@@ -72,6 +73,16 @@ class ApiClient {
7273

7374
return response.json();
7475
}
76+
77+
async compile(input: CompilerInput) {
78+
const response = await fetch("/compiler", {
79+
method: "POST",
80+
headers: { "Content-Type": "application/json" },
81+
body: JSON.stringify({ input }),
82+
});
83+
84+
return response.json();
85+
}
7586
}
7687

7788
export const API = new ApiClient();

src/lib/models/solc.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export type CompilerInput = {
2+
/**
3+
* The language, currently only Solidity is supported.
4+
*/
5+
language: string;
6+
/**
7+
* Name of the file and the content of the file.
8+
* e.g. { 'test.sol': { content: 'contract C { function f() public { L.f(); } }' } }
9+
*/
10+
sources: ContractSources;
11+
/**
12+
* Settings for the compiler.
13+
* e.g. { outputSelection: { '*': { '*': ['*'] } }"
14+
*/
15+
settings: {
16+
outputSelection: Record<string, Record<string, string[]>>;
17+
};
18+
};
19+
20+
export type ContractSources = {
21+
[source: string]: { content: string };
22+
};
23+
24+
export function buildCompilerInput(sources: ContractSources): CompilerInput {
25+
return {
26+
sources,
27+
language: 'Solidity',
28+
settings: {
29+
outputSelection: {
30+
'*': { '*': ['*'] }
31+
}
32+
}
33+
};
34+
}
35+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script lang="ts">
2+
import { API } from "$lib/api";
3+
import { buildCompilerInput, type ContractSources } from "$lib/models/solc";
4+
import { wizardState } from "../state.svelte";
5+
6+
let compilationResult: any;
7+
8+
async function compile() {
9+
if (!wizardState.sources) return;
10+
compilationResult = await API.compile(buildCompilerInput(wizardState.sources));
11+
}
12+
13+
function getMainContractName(sources?: ContractSources) {
14+
if (!sources) return '';
15+
// The first name that is not a dependency
16+
return Object.keys(sources).find(name => !name.startsWith('@'));
17+
}
18+
19+
</script>
20+
21+
<p>
22+
Contract to compile: {getMainContractName(wizardState.sources)}
23+
24+
<button onclick={compile} >
25+
Compile
26+
</button>
27+
</p>

src/lib/wizard/index.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1+
import type { ContractSources } from "../models/solc";
2+
import { wizardState } from "./state.svelte";
3+
4+
export interface DefenderDeployMessage {
5+
kind: 'oz-wizard-defender-deploy';
6+
sources: ContractSources;
7+
}
8+
19
export const initWizardPlugin = () => {
210
// when users configure a contract, the plugin gets the results.
3-
// listenToContracts();
11+
listenToContracts();
12+
}
13+
14+
function listenToContracts() {
15+
window.addEventListener('message', function (e: MessageEvent<DefenderDeployMessage>) {
16+
if (e.data.kind === 'oz-wizard-defender-deploy') {
17+
wizardState.sources = e.data.sources;
18+
}
19+
});
420
}

src/lib/wizard/state.svelte.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { ContractSources } from "../models/solc";
2+
3+
export const wizardState = $state<{ sources: ContractSources | undefined }>({
4+
sources: undefined,
5+
});

src/routes/+page.svelte

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@
2020
// assumes that when in dev mode and
2121
// the ancestor origin is localhost, we are in the wizard
2222
if (dev && ancestorOrigin.includes("localhost")) {
23-
parent = 'wizard';
24-
return;
23+
return parent = 'wizard';
2524
}
2625
27-
if (ancestorOrigin.includes("remix.ethereum")) {
28-
parent = 'remix';
29-
return initRemixPlugin();
26+
if (ancestorOrigin.includes("wizard.openzeppelin")) {
27+
return parent = 'wizard';
3028
}
3129
32-
if (ancestorOrigin.includes("wizard.openzeppelin")) {
33-
parent = 'wizard';
34-
// TODO: init wizard plugin
35-
return;
30+
if (ancestorOrigin.includes("remix.ethereum")) {
31+
return parent = 'remix';
3632
}
33+
3734
});
3835
</script>
3936

src/routes/compiler/+server.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { CompilerInput } from "$lib/models/solc";
2+
import { json } from '@sveltejs/kit';
3+
import { SolidityCompiler } from "./compiler";
4+
import { attempt } from "$lib/utils/attempt";
5+
6+
7+
export async function POST({ request }: { request: Request }) {
8+
const { input }: { input: CompilerInput } = await request.json();
9+
10+
const compiler = new SolidityCompiler();
11+
12+
const [output, error] = await attempt(() => JSON.parse(compiler.compile(input)));
13+
14+
if (error) {
15+
return json({ success: false, error: error.msg });
16+
}
17+
18+
return json({ success: true, data: { output } });
19+
}

0 commit comments

Comments
 (0)