Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/PageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function PageLayout({ children, maxWidth = "max-w-4xl", title, su

const envPrefix =
import.meta.env.VITE_ENV && import.meta.env.VITE_ENV !== "production"
? `(${import.meta.env.VITE_ENV} environment) `
? `(${import.meta.env.VITE_ENV} environment - ${serverUrl}) `
: "";

return (
Expand Down
73 changes: 42 additions & 31 deletions app/components/verification/CompilerSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { useCompilerVersions } from "../../contexts/CompilerVersionsContext";
import type { SolidityVersion, VyperVersion } from "../../contexts/CompilerVersionsContext";
import type { SolidityVersion, VyperVersion, FeVersion } from "../../contexts/CompilerVersionsContext";
import type { Language, SelectedMethod } from "../../types/verification";

interface CompilerSelectorProps {
Expand All @@ -21,14 +21,18 @@ export default function CompilerSelector({
officialSolidityVersions,
vyperVersions,
officialVyperVersions,
feVersions,
officialFeVersions,
isSolidityLoading,
isVyperLoading,
isFeLoading,
solidityError,
vyperError,
feError,
} = useCompilerVersions();

const [showNightlyBuilds, setShowNightlyBuilds] = useState(false);
const [showPrereleases, setShowPrereleases] = useState(false);
const [showPrereleases, setShowPrereleases] = useState(language === "fe");

// Don't show if language is null or if using metadata/framework methods
if (!language || !selectedMethod) {
Expand All @@ -43,8 +47,8 @@ export default function CompilerSelector({
return null;
}

const isLoading = language === "solidity" ? isSolidityLoading : isVyperLoading;
const compilerError = language === "solidity" ? solidityError : vyperError;
const isLoading = language === "solidity" ? isSolidityLoading : language === "vyper" ? isVyperLoading : isFeLoading;
const compilerError = language === "solidity" ? solidityError : language === "vyper" ? vyperError : feError;

if (isLoading) {
return (
Expand Down Expand Up @@ -72,27 +76,32 @@ export default function CompilerSelector({
const getVersionsToShow = () => {
if (language === "solidity") {
return showNightlyBuilds ? solidityVersions : officialSolidityVersions;
} else {
} else if (language === "vyper") {
return showPrereleases ? vyperVersions : officialVyperVersions;
} else {
return feVersions;
}
};

const versionsToShow = getVersionsToShow();

const formatVersionForDisplay = (version: SolidityVersion | VyperVersion) => {
const formatVersionForDisplay = (version: SolidityVersion | VyperVersion | FeVersion) => {
if (language === "solidity") {
return (version as SolidityVersion).version;
} else if (language === "vyper") {
return (version as VyperVersion).longVersion;
} else {
const vyperVersion = version as VyperVersion;
return vyperVersion.longVersion;
return (version as FeVersion).version;
}
};

const getVersionValue = (version: SolidityVersion | VyperVersion) => {
const getVersionValue = (version: SolidityVersion | VyperVersion | FeVersion) => {
if (language === "solidity") {
return (version as SolidityVersion).version;
} else {
} else if (language === "vyper") {
return (version as VyperVersion).longVersion;
} else {
return (version as FeVersion).version;
}
};

Expand Down Expand Up @@ -129,27 +138,29 @@ export default function CompilerSelector({
</div>
</div>

<div className="flex items-center">
<input
type="checkbox"
id={`show${language === "solidity" ? "Nightly" : "Prerelease"}`}
checked={language === "solidity" ? showNightlyBuilds : showPrereleases}
onChange={(e) => {
if (language === "solidity") {
setShowNightlyBuilds(e.target.checked);
} else {
setShowPrereleases(e.target.checked);
}
}}
className="h-4 w-4 text-cerulean-blue-600 focus:ring-cerulean-blue-500 border-gray-300 rounded"
/>
<label
htmlFor={`show${language === "solidity" ? "Nightly" : "Prerelease"}`}
className="ml-2 block text-sm text-gray-700"
>
{language === "solidity" ? "Show nightly builds" : "Show prereleases"}
</label>
</div>
{language !== "fe" && (
<div className="flex items-center">
<input
type="checkbox"
id={`show${language === "solidity" ? "Nightly" : "Prerelease"}`}
checked={language === "solidity" ? showNightlyBuilds : showPrereleases}
onChange={(e) => {
if (language === "solidity") {
setShowNightlyBuilds(e.target.checked);
} else {
setShowPrereleases(e.target.checked);
}
}}
className="h-4 w-4 text-cerulean-blue-600 focus:ring-cerulean-blue-500 border-gray-300 rounded"
/>
<label
htmlFor={`show${language === "solidity" ? "Nightly" : "Prerelease"}`}
className="ml-2 block text-sm text-gray-700"
>
{language === "solidity" ? "Show nightly builds" : "Show alpha/prereleases"}
</label>
</div>
)}
</div>
</div>
);
Expand Down
7 changes: 5 additions & 2 deletions app/components/verification/CompilerSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ export default function CompilerSettings({
onOptimizerEnabledChange,
onOptimizerRunsChange,
}: CompilerSettingsProps) {
// Only show for single-file and multiple-files methods
const shouldShow = !isFrameworkMethod && (selectedMethod === "single-file" || selectedMethod === "multiple-files");
// Only show for single-file and multiple-files methods, and not for Fe (no compiler settings)
const shouldShow =
!isFrameworkMethod &&
selectedLanguage !== "fe" &&
(selectedMethod === "single-file" || selectedMethod === "multiple-files");

if (!shouldShow) return null;

Expand Down
31 changes: 27 additions & 4 deletions app/components/verification/ContractIdentifier.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ export default function ContractIdentifier({
fullIdentifier: `${filePath}:${contractName}`,
});
}
} else if (selectedLanguage === "fe" && filePath.endsWith(".fe")) {
const feContracts = parseFeFileContent(filePath, sourceContent);
contracts.push(...feContracts);
}
}
}
Expand All @@ -110,6 +113,10 @@ export default function ContractIdentifier({
contractName,
fullIdentifier: `${file.name}:${contractName}`,
});
} else if (selectedLanguage === "fe" && file.name.endsWith(".fe")) {
const content = await file.text();
const feContracts = parseFeFileContent(file.name, content);
contracts.push(...feContracts);
}
}
}
Expand Down Expand Up @@ -158,6 +165,19 @@ export default function ContractIdentifier({
}
}, [isDropdownOpen]);

const parseFeFileContent = (fileName: string, content: string): ParsedContract[] => {
const contracts: ParsedContract[] = [];
const matches = content.matchAll(/pub\s+contract\s+(\w+)/g);
for (const match of matches) {
contracts.push({
fileName,
contractName: match[1],
fullIdentifier: `${fileName}:${match[1]}`,
});
}
return contracts;
};

const parseFileContent = async (fileName: string | null, content: string): Promise<ParsedContract[]> => {
try {
const ast = parse(content, {
Expand All @@ -172,7 +192,7 @@ export default function ContractIdentifier({
for (const child of ast.children) {
if (child.type === "ContractDefinition" && child.name) {
if (!fileName) {
const extension = selectedLanguage === "solidity" ? ".sol" : ".vy";
const extension = selectedLanguage === "solidity" ? ".sol" : selectedLanguage === "vyper" ? ".vy" : ".fe";
fileName = `${child.name}${extension}`;
}

Expand Down Expand Up @@ -207,6 +227,9 @@ export default function ContractIdentifier({
if (selectedLanguage === "vyper") {
return "contracts/MyContract.vy:MyContract";
}
if (selectedLanguage === "fe") {
return "src/counter.fe:Counter";
}
return "contracts/Storage.sol:Storage";
};

Expand Down Expand Up @@ -267,12 +290,12 @@ export default function ContractIdentifier({
{uploadedFiles.length > 0 &&
parsedContracts.length === 0 &&
!isParsingFiles &&
selectedLanguage === "vyper" && (
(selectedLanguage === "vyper" || selectedLanguage === "fe") && (
<div className="mt-2">
<p className="text-xs text-gray-500">Available Vyper files:</p>
<p className="text-xs text-gray-500">Available {selectedLanguage === "vyper" ? "Vyper" : "Fe"} files:</p>
<ul className="text-xs text-gray-500 ml-2">
{uploadedFiles
.filter((file) => file.name.endsWith(".vy"))
.filter((file) => file.name.endsWith(selectedLanguage === "vyper" ? ".vy" : ".fe"))
.map((file, index) => (
<li key={index}>• {file.name}</li>
))}
Expand Down
2 changes: 1 addition & 1 deletion app/components/verification/EvmVersionSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function EvmVersionSelector({
selectedEvmVersion,
onEvmVersionSelect,
}: EvmVersionSelectorProps) {
if (!selectedLanguage) return null;
if (!selectedLanguage || selectedLanguage === "fe") return null;

const evmVersions = selectedLanguage === "vyper" ? VYPER_EVM_VERSIONS : SOLIDITY_EVM_VERSIONS;

Expand Down
12 changes: 8 additions & 4 deletions app/components/verification/FileUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ const getLanguageExtensions = (language: Language | null): string[] => {
return [".sol"];
case "vyper":
return [".vy"];
case "fe":
return [".fe"];
default:
return [".sol", ".vy"];
return [".sol", ".vy", ".fe"];
}
};

const getFileRequirements = (method: VerificationMethod, language: Language | null): FileRequirement => {
const sourceExtensions = getLanguageExtensions(language);
const languageName = language === "vyper" ? "Vyper" : "Solidity";
const languageName = language === "vyper" ? "Vyper" : language === "fe" ? "Fe" : "Solidity";

switch (method) {
case "std-json":
Expand Down Expand Up @@ -99,7 +101,7 @@ export default function FileUpload({
if (["std-json", "metadata-json", "build-info"].includes(selectedMethod)) {
return ".json";
}
return selectedLanguage === "vyper" ? ".vy" : ".sol";
return selectedLanguage === "vyper" ? ".vy" : selectedLanguage === "fe" ? ".fe" : ".sol";
};

const validateFileName = (fileName: string): string | null => {
Expand Down Expand Up @@ -238,6 +240,8 @@ export default function FileUpload({
return <img src="/solidity.svg" alt="Solidity" className="w-5 h-5" />;
case "vy":
return <img src="/vyper.svg" alt="Vyper" className="w-5 h-5" />;
case "fe":
return <img src="/fe.svg" alt="Fe" className="w-5 h-5" />;
default:
return <span className="text-lg">❓</span>;
}
Expand Down Expand Up @@ -423,7 +427,7 @@ export default function FileUpload({
onFilesChange([]);
}
}}
placeholder={selectedLanguage === "vyper" ? "MyContract.vy" : "MyContract.sol"}
placeholder={selectedLanguage === "vyper" ? "MyContract.vy" : selectedLanguage === "fe" ? "MyContract.fe" : "MyContract.sol"}
className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-cerulean-blue-500 focus:border-cerulean-blue-500 ${
fileNameError ? "border-red-300" : "border-gray-300"
}`}
Expand Down
19 changes: 19 additions & 0 deletions app/components/verification/LanguageSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ export default function LanguageSelector({ selectedLanguage, onLanguageSelect }:
Vyper
</h3>
</button>

<button
type="button"
onClick={() => onLanguageSelect("fe")}
className={`w-32 p-4 border-2 rounded-lg text-center transition-all duration-200 ${
selectedLanguage === "fe"
? "border-cerulean-blue-500 bg-cerulean-blue-50"
: "border-gray-300 hover:border-cerulean-blue-300 hover:bg-gray-50"
}`}
>
<img src="/fe.svg" alt="Fe" className="mx-auto w-8 h-8 mb-2" />
<h3
className={`text-sm font-medium ${
selectedLanguage === "fe" ? "text-cerulean-blue-600" : "text-gray-700"
}`}
>
Fe
</h3>
</button>
</div>
</div>
);
Expand Down
Loading
Loading