diff --git a/app/components/PageLayout.tsx b/app/components/PageLayout.tsx
index 0f778eb..1b31f27 100644
--- a/app/components/PageLayout.tsx
+++ b/app/components/PageLayout.tsx
@@ -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 (
diff --git a/app/components/verification/CompilerSelector.tsx b/app/components/verification/CompilerSelector.tsx
index 7684d63..ec7d3c6 100644
--- a/app/components/verification/CompilerSelector.tsx
+++ b/app/components/verification/CompilerSelector.tsx
@@ -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 {
@@ -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) {
@@ -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 (
@@ -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;
}
};
@@ -129,27 +138,29 @@ export default function CompilerSelector({
-
- {
- 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"
- />
-
-
+ {language !== "fe" && (
+
+ {
+ 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"
+ />
+
+
+ )}
);
diff --git a/app/components/verification/CompilerSettings.tsx b/app/components/verification/CompilerSettings.tsx
index 6bb631d..c8c45a4 100644
--- a/app/components/verification/CompilerSettings.tsx
+++ b/app/components/verification/CompilerSettings.tsx
@@ -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;
diff --git a/app/components/verification/ContractIdentifier.tsx b/app/components/verification/ContractIdentifier.tsx
index 0e9e3e7..4e68481 100644
--- a/app/components/verification/ContractIdentifier.tsx
+++ b/app/components/verification/ContractIdentifier.tsx
@@ -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);
}
}
}
@@ -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);
}
}
}
@@ -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 => {
try {
const ast = parse(content, {
@@ -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}`;
}
@@ -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";
};
@@ -267,12 +290,12 @@ export default function ContractIdentifier({
{uploadedFiles.length > 0 &&
parsedContracts.length === 0 &&
!isParsingFiles &&
- selectedLanguage === "vyper" && (
+ (selectedLanguage === "vyper" || selectedLanguage === "fe") && (
-
Available Vyper files:
+
Available {selectedLanguage === "vyper" ? "Vyper" : "Fe"} files:
{uploadedFiles
- .filter((file) => file.name.endsWith(".vy"))
+ .filter((file) => file.name.endsWith(selectedLanguage === "vyper" ? ".vy" : ".fe"))
.map((file, index) => (
- • {file.name}
))}
diff --git a/app/components/verification/EvmVersionSelector.tsx b/app/components/verification/EvmVersionSelector.tsx
index 4c7e3b2..2a1c4e7 100644
--- a/app/components/verification/EvmVersionSelector.tsx
+++ b/app/components/verification/EvmVersionSelector.tsx
@@ -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;
diff --git a/app/components/verification/FileUpload.tsx b/app/components/verification/FileUpload.tsx
index 155e3bb..ee7c59f 100644
--- a/app/components/verification/FileUpload.tsx
+++ b/app/components/verification/FileUpload.tsx
@@ -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":
@@ -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 => {
@@ -238,6 +240,8 @@ export default function FileUpload({
return
;
case "vy":
return
;
+ case "fe":
+ return
;
default:
return ❓;
}
@@ -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"
}`}
diff --git a/app/components/verification/LanguageSelector.tsx b/app/components/verification/LanguageSelector.tsx
index 3e50dc9..af5b495 100644
--- a/app/components/verification/LanguageSelector.tsx
+++ b/app/components/verification/LanguageSelector.tsx
@@ -47,6 +47,25 @@ export default function LanguageSelector({ selectedLanguage, onLanguageSelect }:
Vyper
+
+
);
diff --git a/app/contexts/CompilerVersionsContext.tsx b/app/contexts/CompilerVersionsContext.tsx
index 7f44e76..7c3f7a1 100644
--- a/app/contexts/CompilerVersionsContext.tsx
+++ b/app/contexts/CompilerVersionsContext.tsx
@@ -12,6 +12,11 @@ export interface VyperVersion {
isPrerelease: boolean;
}
+export interface FeVersion {
+ version: string;
+ isPrerelease: boolean;
+}
+
interface CompilerVersionsContextType {
// Solidity versions
solidityVersions: SolidityVersion[];
@@ -21,19 +26,26 @@ interface CompilerVersionsContextType {
vyperVersions: VyperVersion[];
officialVyperVersions: VyperVersion[];
+ // Fe versions
+ feVersions: FeVersion[];
+ officialFeVersions: FeVersion[];
+
// Loading states
isSolidityLoading: boolean;
isVyperLoading: boolean;
+ isFeLoading: boolean;
// Error states
solidityError: string | null;
vyperError: string | null;
+ feError: string | null;
}
const CompilerVersionsContext = createContext(undefined);
const SOLC_VERSIONS_LIST_URL = "https://raw.githubusercontent.com/ethereum/solc-bin/gh-pages/bin/list.txt";
const VYPER_VERSIONS_LIST_URL = "https://vyper-releases-mirror.hardhat.org/list.json";
+const FE_VERSIONS_LIST_URL = "https://api.github.com/repos/argotorg/fe/releases";
function formatSolidityVersionName(filename: string): SolidityVersion {
// Remove "soljson-v" prefix and ".js" suffix
@@ -66,10 +78,15 @@ export function CompilerVersionsProvider({ children }: { children: React.ReactNo
const [vyperVersions, setVyperVersions] = useState([]);
const [officialVyperVersions, setOfficialVyperVersions] = useState([]);
+ const [feVersions, setFeVersions] = useState([]);
+ const [officialFeVersions, setOfficialFeVersions] = useState([]);
+
const [isSolidityLoading, setIsSolidityLoading] = useState(true);
const [isVyperLoading, setIsVyperLoading] = useState(true);
+ const [isFeLoading, setIsFeLoading] = useState(true);
const [solidityError, setSolidityError] = useState(null);
const [vyperError, setVyperError] = useState(null);
+ const [feError, setFeError] = useState(null);
// Fetch Solidity versions
useEffect(() => {
@@ -123,6 +140,30 @@ export function CompilerVersionsProvider({ children }: { children: React.ReactNo
});
}, []);
+ // Fetch Fe versions
+ useEffect(() => {
+ fetch(FE_VERSIONS_LIST_URL)
+ .then((response) => response.json())
+ .then((data: { tag_name: string; published_at: string; assets: { name: string }[] }[]) => {
+ const allVersionsList: FeVersion[] = data
+ .filter((release) => release.assets.length > 0 && new Date(release.published_at) >= new Date("2026-03-20"))
+ .map((release) => {
+ const version = release.tag_name.replace(/^v/, "");
+ const isPrerelease = /alpha|beta|rc/i.test(version);
+ return { version, isPrerelease };
+ });
+
+ setFeVersions(allVersionsList);
+ setOfficialFeVersions(allVersionsList.filter((v) => !v.isPrerelease));
+ setIsFeLoading(false);
+ })
+ .catch((error) => {
+ console.error("Failed to fetch Fe versions:", error);
+ setIsFeLoading(false);
+ setFeError("Failed to fetch Fe compiler versions");
+ });
+ }, []);
+
return (
{children}
diff --git a/app/data/verificationMethods.tsx b/app/data/verificationMethods.tsx
index 56dd28c..921a7e1 100644
--- a/app/data/verificationMethods.tsx
+++ b/app/data/verificationMethods.tsx
@@ -53,6 +53,7 @@ export const solidityMetadataMethod: VerificationMethodObject = {
export const verificationMethods: VerificationMethods = {
solidity: [...baseVerificationMethods, solidityMetadataMethod],
vyper: baseVerificationMethods,
+ fe: baseVerificationMethods,
};
export const frameworkMethods: FrameworkMethodObject[] = [
diff --git a/app/hooks/useFormValidation.ts b/app/hooks/useFormValidation.ts
index 0d532c7..75a8e2a 100644
--- a/app/hooks/useFormValidation.ts
+++ b/app/hooks/useFormValidation.ts
@@ -87,9 +87,12 @@ export function useFormValidation({
const areFilesRequired = languageString && selectedMethod &&
["single-file", "multiple-files", "std-json", "metadata-json", "build-info"].includes(selectedMethod);
- // Check if EVM version is required (for all languages, not for metadata-json, hardhat, or foundry methods)
+ // Check if EVM version is required (not for Fe which has no EVM version setting, or metadata-json/framework methods)
const isEvmVersionRequired =
- languageString && selectedMethod && ["single-file", "multiple-files"].includes(selectedMethod);
+ languageString &&
+ selectedLanguage !== "fe" &&
+ selectedMethod &&
+ ["single-file", "multiple-files"].includes(selectedMethod);
const validateFiles = () => {
if (!areFilesRequired) return true;
diff --git a/app/types/verification.ts b/app/types/verification.ts
index 8c5d31f..4b606ee 100644
--- a/app/types/verification.ts
+++ b/app/types/verification.ts
@@ -1,4 +1,4 @@
-export type Language = "solidity" | "vyper";
+export type Language = "solidity" | "vyper" | "fe";
// Verification method IDs
export type VerificationMethod = "single-file" | "multiple-files" | "std-json" | "metadata-json" | "build-info";
@@ -27,6 +27,7 @@ export interface FrameworkMethodObject {
export interface VerificationMethods {
solidity: VerificationMethodObject[];
vyper: VerificationMethodObject[];
+ fe: VerificationMethodObject[];
}
export interface FrameworkMessages {
diff --git a/app/utils/sourcifyApi.ts b/app/utils/sourcifyApi.ts
index 9f11223..9e42c76 100644
--- a/app/utils/sourcifyApi.ts
+++ b/app/utils/sourcifyApi.ts
@@ -95,13 +95,13 @@ async function buildStandardJsonInput(
}
// For Vyper, no optimization settings are added
- // Only include evmVersion if it's not "default"
- if (settings.evmVersion?.toLowerCase() !== "default") {
+ // Only include evmVersion if it's set and not "default"
+ if (settings.evmVersion && settings.evmVersion.toLowerCase() !== "default") {
standardJsonSettings.evmVersion = settings.evmVersion;
}
return {
- language: language === "vyper" ? "Vyper" : "Solidity",
+ language: language === "vyper" ? "Vyper" : language === "fe" ? "Fe" : "Solidity",
sources,
settings: standardJsonSettings,
};
diff --git a/package-lock.json b/package-lock.json
index 26d8968..bb6685a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,33 +5,33 @@
"packages": {
"": {
"dependencies": {
- "@ethereum-sourcify/lib-sourcify": "^2.3.0",
- "@headlessui/react": "^2.2.4",
+ "@ethereum-sourcify/lib-sourcify": "2.3.0",
+ "@headlessui/react": "2.2.4",
"@react-router/node": "^7.5.3",
- "@react-router/serve": "^7.5.3",
- "@solidity-parser/parser": "^0.20.1",
+ "@react-router/serve": "7.6.2",
+ "@solidity-parser/parser": "0.20.1",
"diff": "^8.0.2",
- "ethers": "^6.14.4",
- "fuse.js": "^7.1.0",
- "isbot": "^5.1.27",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-icons": "^5.5.0",
+ "ethers": "6.15.0",
+ "fuse.js": "7.1.0",
+ "isbot": "5.1.28",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "react-icons": "5.5.0",
"react-router": "^7.5.3",
- "react-tooltip": "^5.29.1",
- "serve": "^14.2.5"
+ "react-tooltip": "5.29.1",
+ "serve": "14.2.5"
},
"devDependencies": {
- "@ethereum-sourcify/compilers-types": "^1.0.7",
- "@react-router/dev": "^7.5.3",
- "@tailwindcss/vite": "^4.1.4",
- "@types/node": "^20",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "tailwindcss": "^4.1.4",
- "typescript": "^5.8.3",
+ "@ethereum-sourcify/compilers-types": "1.0.7",
+ "@react-router/dev": "7.6.2",
+ "@tailwindcss/vite": "4.1.10",
+ "@types/node": "20.19.1",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "tailwindcss": "4.1.10",
+ "typescript": "5.8.3",
"vite": "^6.3.3",
- "vite-tsconfig-paths": "^5.1.4"
+ "vite-tsconfig-paths": "5.1.4"
}
},
"node_modules/@adraffy/ens-normalize": {
@@ -1423,6 +1423,7 @@
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz",
"integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.26.16",
"@react-aria/focus": "^3.20.2",
@@ -2198,7 +2199,8 @@
"node_modules/@solidity-parser/parser": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.1.tgz",
- "integrity": "sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw=="
+ "integrity": "sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw==",
+ "license": "MIT"
},
"node_modules/@swc/helpers": {
"version": "0.5.17",
@@ -2436,6 +2438,66 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "1.4.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.0.2",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.4.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.10",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.9.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
+ "version": "0.9.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
+ "version": "2.8.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "0BSD",
+ "optional": true
+ },
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.10",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz",
@@ -3381,9 +3443,10 @@
}
},
"node_modules/diff": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
- "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==",
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
+ "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
@@ -3628,6 +3691,7 @@
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
+ "license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
@@ -3635,12 +3699,14 @@
"node_modules/ethers/node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
- "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "license": "0BSD"
},
"node_modules/ethers/node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
},
"node_modules/execa": {
"version": "5.1.1",
@@ -3876,6 +3942,7 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
"integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
+ "license": "Apache-2.0",
"engines": {
"node": ">=10"
}
@@ -5304,6 +5371,7 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
"peerDependencies": {
"react": "*"
}
@@ -5353,6 +5421,7 @@
"version": "5.29.1",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.29.1.tgz",
"integrity": "sha512-rmJmEb/p99xWhwmVT7F7riLG08wwKykjHiMGbDPloNJk3tdI73oHsVOwzZ4SRjqMdd5/xwb/4nmz0RcoMfY7Bw==",
+ "license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.1",
"classnames": "^2.3.0"
@@ -6342,9 +6411,9 @@
}
},
"node_modules/vite": {
- "version": "6.3.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
- "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index 965f91a..fc51157 100644
--- a/package.json
+++ b/package.json
@@ -9,32 +9,32 @@
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
- "@ethereum-sourcify/lib-sourcify": "^2.3.0",
- "@headlessui/react": "^2.2.4",
+ "@ethereum-sourcify/lib-sourcify": "2.3.0",
+ "@headlessui/react": "2.2.4",
"@react-router/node": "^7.5.3",
- "@react-router/serve": "^7.5.3",
- "@solidity-parser/parser": "^0.20.1",
+ "@react-router/serve": "7.6.2",
+ "@solidity-parser/parser": "0.20.1",
"diff": "^8.0.2",
- "ethers": "^6.14.4",
- "fuse.js": "^7.1.0",
- "isbot": "^5.1.27",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-icons": "^5.5.0",
+ "ethers": "6.15.0",
+ "fuse.js": "7.1.0",
+ "isbot": "5.1.28",
+ "react": "19.1.0",
+ "react-dom": "19.1.0",
+ "react-icons": "5.5.0",
"react-router": "^7.5.3",
- "react-tooltip": "^5.29.1",
- "serve": "^14.2.5"
+ "react-tooltip": "5.29.1",
+ "serve": "14.2.5"
},
"devDependencies": {
- "@ethereum-sourcify/compilers-types": "^1.0.7",
- "@react-router/dev": "^7.5.3",
- "@tailwindcss/vite": "^4.1.4",
- "@types/node": "^20",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "tailwindcss": "^4.1.4",
- "typescript": "^5.8.3",
+ "@ethereum-sourcify/compilers-types": "1.0.7",
+ "@react-router/dev": "7.6.2",
+ "@tailwindcss/vite": "4.1.10",
+ "@types/node": "20.19.1",
+ "@types/react": "19.1.8",
+ "@types/react-dom": "19.1.6",
+ "tailwindcss": "4.1.10",
+ "typescript": "5.8.3",
"vite": "^6.3.3",
- "vite-tsconfig-paths": "^5.1.4"
+ "vite-tsconfig-paths": "5.1.4"
}
}
diff --git a/public/fe.svg b/public/fe.svg
new file mode 100644
index 0000000..05d84dd
--- /dev/null
+++ b/public/fe.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..9ff60cb
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,27 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "configMigration": true,
+ "extends": ["config:recommended", "schedule:daily"],
+ "packageRules": [
+ {
+ "matchUpdateTypes": [
+ "minor",
+ "patch",
+ "pin",
+ "digest",
+ "lockFileMaintenance",
+ "rollback",
+ "bump"
+ ],
+ "groupName": "all patch and minor dependencies",
+ "groupSlug": "all-patch-and-minor"
+ }
+ ],
+ "ignoreDeps": ["node", "cimg/node"],
+ "major": {
+ "dependencyDashboardApproval": true
+ },
+ "rangeStrategy": "pin",
+ "timezone": "Europe/Berlin",
+ "schedule": ["before 6am on tuesday"]
+}