diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea95d52ad..788bc8960 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features
+- [#1213](https://github.com/alleslabs/celatone-frontend/pull/1213) EVM verification status modal, and highlight bar
- [#1211](https://github.com/alleslabs/celatone-frontend/pull/1211) Implement evm gas refund logic
- [#1210](https://github.com/alleslabs/celatone-frontend/pull/1210) Add EVM contract details code preview
- [#1209](https://github.com/alleslabs/celatone-frontend/pull/1209) Implement evm contract details interaction
diff --git a/src/lib/components/evm-verify-section/FailedDetails.tsx b/src/lib/components/evm-verify-section/FailedDetails.tsx
new file mode 100644
index 000000000..bba6febd9
--- /dev/null
+++ b/src/lib/components/evm-verify-section/FailedDetails.tsx
@@ -0,0 +1,72 @@
+import { Button, HStack, Text } from "@chakra-ui/react";
+
+import { useInternalNavigate, useMobile } from "lib/app-provider";
+import { EvmVerifyInfo } from "lib/services/types";
+import type { HexAddr20 } from "lib/types";
+import { formatUTC } from "lib/utils";
+import { EvmVerifyStatusModalWithTrigger } from "../modal/evm-verify-status";
+
+interface FailedDetailsProps {
+ contractAddress: HexAddr20;
+ evmVerifyInfo: EvmVerifyInfo;
+}
+
+export const FailedDetails = ({
+ contractAddress,
+ evmVerifyInfo,
+}: FailedDetailsProps) => {
+ const isMobile = useMobile();
+ const navigate = useInternalNavigate();
+
+ const handleNavigate = () =>
+ navigate({
+ pathname: "/evm-contracts/verify",
+ query: { contractAddress },
+ });
+
+ if (isMobile)
+ return (
+ <>
+
+ Verification failed: Verification was submitted on{" "}
+ {formatUTC(evmVerifyInfo.submittedTimestamp)} but an error occurred.
+
+
+ If you are the owner, you can reverify this contract on the desktop
+ interface.
+
+
+ Verify Details
+
+ }
+ />
+ >
+ );
+
+ return (
+ <>
+
+ Verification failed: Verification was submitted on{" "}
+ {formatUTC(evmVerifyInfo.submittedTimestamp)} but an error occurred.
+
+
+
+ Verify Details
+
+ }
+ />
+
+
+ >
+ );
+};
diff --git a/src/lib/components/evm-verify-section/InProgressDetails.tsx b/src/lib/components/evm-verify-section/InProgressDetails.tsx
new file mode 100644
index 000000000..364822155
--- /dev/null
+++ b/src/lib/components/evm-verify-section/InProgressDetails.tsx
@@ -0,0 +1,31 @@
+import { Button, Text } from "@chakra-ui/react";
+
+import type { HexAddr20 } from "lib/types";
+import { EvmVerifyInfo } from "lib/services/types";
+import { EvmVerifyStatusModalWithTrigger } from "../modal/evm-verify-status";
+
+interface InProgressDetailsProps {
+ contractAddress: HexAddr20;
+ evmVerifyInfo: EvmVerifyInfo;
+}
+
+export const InProgressDetails = ({
+ contractAddress,
+ evmVerifyInfo,
+}: InProgressDetailsProps) => (
+ <>
+
+ Contract verification is in progress and may take several hours depending
+ on contract complexity.
+
+
+ View Verification Details
+
+ }
+ />
+ >
+);
diff --git a/src/lib/components/evm-verify-section/NotVerifiedDetails.tsx b/src/lib/components/evm-verify-section/NotVerifiedDetails.tsx
index 9337d959d..ca8dd3583 100644
--- a/src/lib/components/evm-verify-section/NotVerifiedDetails.tsx
+++ b/src/lib/components/evm-verify-section/NotVerifiedDetails.tsx
@@ -1,4 +1,4 @@
-import { Button, Flex, Text } from "@chakra-ui/react";
+import { Button, Text } from "@chakra-ui/react";
import { useInternalNavigate, useMobile } from "lib/app-provider";
import type { HexAddr20 } from "lib/types";
@@ -19,51 +19,41 @@ export const NotVerifiedDetails = ({
query: { contractAddress },
});
+ if (isMobile)
+ return (
+ <>
+
+ This contract has not been verified. If you are the owner, you can
+ verify it to allow other users to view the source code
+
+
+ Verification is only currently supported on desktop.
+
+ >
+ );
+
return (
-
- {isMobile ? (
- <>
-
- This contract has not been verified. If you are the owner, you can
- verify it to allow other users to view the source code
-
-
- Verification is only currently supported on desktop.
-
- >
- ) : (
- <>
-
- This contract has not been verified. If you are the owner, you can{" "}
-
- verify it
- {" "}
- to allow other users to view the source code
-
-
- >
- )}
-
+ <>
+
+ This contract has not been verified. If you are the owner, you can{" "}
+
+ verify it
+ {" "}
+ to allow other users to view the source code
+
+
+ >
);
};
diff --git a/src/lib/components/evm-verify-section/VerifiedDetails.tsx b/src/lib/components/evm-verify-section/VerifiedDetails.tsx
new file mode 100644
index 000000000..dddb8d83e
--- /dev/null
+++ b/src/lib/components/evm-verify-section/VerifiedDetails.tsx
@@ -0,0 +1,29 @@
+import { Text } from "@chakra-ui/react";
+
+import { TabIndex } from "lib/pages/evm-contract-details/types";
+import type { HexAddr20 } from "lib/types";
+import { AppLink } from "../AppLink";
+
+interface VerifiedDetailsProps {
+ contractAddress: HexAddr20;
+}
+
+export const VerifiedDetails = ({ contractAddress }: VerifiedDetailsProps) => (
+
+ This contract source code is verified with the exact match. You can view its{" "}
+
+
+ Source Code.
+
+
+
+);
diff --git a/src/lib/components/evm-verify-section/index.ts b/src/lib/components/evm-verify-section/index.ts
deleted file mode 100644
index c97512379..000000000
--- a/src/lib/components/evm-verify-section/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./NotVerifiedDetails";
diff --git a/src/lib/components/evm-verify-section/index.tsx b/src/lib/components/evm-verify-section/index.tsx
new file mode 100644
index 000000000..7dfed134e
--- /dev/null
+++ b/src/lib/components/evm-verify-section/index.tsx
@@ -0,0 +1,65 @@
+import { Flex } from "@chakra-ui/react";
+
+import type { HexAddr20, Option } from "lib/types";
+
+import { NotVerifiedDetails } from "./NotVerifiedDetails";
+import { EvmVerifyInfo } from "lib/services/types";
+import { useMobile } from "lib/app-provider";
+import { VerifiedDetails } from "./VerifiedDetails";
+import { FailedDetails } from "./FailedDetails";
+import { InProgressDetails } from "./InProgressDetails";
+
+interface EvmVerifySectionProps {
+ contractAddress: HexAddr20;
+ evmVerifyInfo: Option;
+}
+
+const EvmVerifySectionBody = ({
+ contractAddress,
+ evmVerifyInfo,
+}: EvmVerifySectionProps) => {
+ if (!evmVerifyInfo) {
+ return ;
+ }
+
+ const { errorMessage, isVerified } = evmVerifyInfo;
+
+ if (errorMessage) {
+ return (
+
+ );
+ }
+
+ if (isVerified) {
+ return ;
+ }
+
+ return (
+
+ );
+};
+
+export const EvmVerifySection = (props: EvmVerifySectionProps) => {
+ const isMobile = useMobile();
+
+ return (
+
+
+
+ );
+};
diff --git a/src/lib/components/modal/evm-verify-status/EvmVerifyAlert.tsx b/src/lib/components/modal/evm-verify-status/EvmVerifyAlert.tsx
new file mode 100644
index 000000000..fa93fd8b2
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/EvmVerifyAlert.tsx
@@ -0,0 +1,38 @@
+import { Alert, AlertDescription, Flex, Text } from "@chakra-ui/react";
+
+import { CustomIcon } from "lib/components/icon";
+
+interface EvmVerifyAlertProps {
+ errorMsg: string;
+}
+export const EvmVerifyAlert = ({ errorMsg }: EvmVerifyAlertProps) => (
+
+
+
+
+
+ Verification failed
+
+
+ {errorMsg}
+
+
+
+
+);
diff --git a/src/lib/components/modal/evm-verify-status/EvmVerifyProcess.tsx b/src/lib/components/modal/evm-verify-status/EvmVerifyProcess.tsx
new file mode 100644
index 000000000..417500adb
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/EvmVerifyProcess.tsx
@@ -0,0 +1,70 @@
+import { Box, Flex, Text } from "@chakra-ui/react";
+import { useMobile } from "lib/app-provider";
+import { EvmVerifyInfo } from "lib/services/types";
+import { getProcessSteps } from "./utils";
+import { formatUTC } from "lib/utils";
+import { EvmVerifyProcessStepIcon } from "./EvmVerifyProcessStepIcon";
+
+interface EvmVerifyProcessProps {
+ evmVerifyInfo: EvmVerifyInfo;
+}
+
+export const EvmVerifyProcess = ({ evmVerifyInfo }: EvmVerifyProcessProps) => {
+ const isMobile = useMobile();
+ const steps = getProcessSteps(evmVerifyInfo);
+
+ return (
+
+
+ Verification Process
+
+
+ {steps.map((step, index) => (
+
+
+
+
+ {index < steps.length - 1 && (
+
+ )}
+
+
+
+ {step.label}
+
+ {isMobile && step.timestamp && (
+
+ {formatUTC(step.timestamp)}
+
+ )}
+ {step.errorMsg && (
+
+ {step.errorMsg}
+
+ )}
+
+
+
+
+ {!isMobile && step.timestamp && (
+
+ {formatUTC(step.timestamp)}
+
+ )}
+ {step.state === "In Progress" && (
+
+ {step.state}
+
+ )}
+
+
+ ))}
+
+
+ );
+};
diff --git a/src/lib/components/modal/evm-verify-status/EvmVerifyProcessStepIcon.tsx b/src/lib/components/modal/evm-verify-status/EvmVerifyProcessStepIcon.tsx
new file mode 100644
index 000000000..e4ebbbfbf
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/EvmVerifyProcessStepIcon.tsx
@@ -0,0 +1,41 @@
+import { Box, Flex } from "@chakra-ui/react";
+
+import { CustomIcon } from "lib/components/icon";
+
+export const EvmVerifyProcessStepIcon = ({ state }: { state: string }) => {
+ switch (state) {
+ case "Failed":
+ return ;
+ case "Completed":
+ return ;
+ case "In Progress":
+ return (
+
+ );
+ case "Pending":
+ default:
+ return (
+
+ );
+ }
+};
diff --git a/src/lib/components/modal/evm-verify-status/EvmVerifyRequestInfo.tsx b/src/lib/components/modal/evm-verify-status/EvmVerifyRequestInfo.tsx
new file mode 100644
index 000000000..9a791f461
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/EvmVerifyRequestInfo.tsx
@@ -0,0 +1,90 @@
+import type { HexAddr20, Option } from "lib/types";
+import { EvmVerifyInfo } from "lib/services/types";
+import { Flex, HStack } from "@chakra-ui/react";
+import { Divider, Text, TextProps } from "@chakra-ui/react";
+import { ExplorerLink } from "lib/components/ExplorerLink";
+import { formatUTC, getLicenseTypeLabel } from "lib/utils";
+import { useMobile } from "lib/app-provider";
+
+const baseTextStyle: TextProps = {
+ color: "text.dark",
+ variant: "body2",
+ whiteSpace: "nowrap",
+};
+
+interface EvmVerifyRequestInfoProps {
+ contractAddress: HexAddr20;
+ evmVerifyInfo: Option;
+}
+
+export const EvmVerifyRequestInfo = ({
+ contractAddress,
+ evmVerifyInfo,
+}: EvmVerifyRequestInfoProps) => {
+ const isMobile = useMobile();
+
+ // Verification not submitted
+ if (!evmVerifyInfo)
+ return (
+ <>
+
+ Contract Address:
+
+
+
+
+ No verification was submitted.
+
+ >
+ );
+
+ return (
+ <>
+
+
+ Contract Address:
+
+
+
+ License Type:
+
+ {getLicenseTypeLabel(evmVerifyInfo.license)}
+
+
+
+
+
+
+ Language:
+
+ {evmVerifyInfo.language}
+
+
+
+ Compiler Version:
+
+ {evmVerifyInfo.compilerVersion}
+
+
+
+ Submitted on:
+
+ {formatUTC(evmVerifyInfo.submittedTimestamp)}
+
+
+
+ >
+ );
+};
diff --git a/src/lib/components/modal/evm-verify-status/index.tsx b/src/lib/components/modal/evm-verify-status/index.tsx
new file mode 100644
index 000000000..38ea89519
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/index.tsx
@@ -0,0 +1,103 @@
+import {
+ Button,
+ Divider,
+ Flex,
+ Heading,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalHeader,
+ ModalOverlay,
+ useDisclosure,
+} from "@chakra-ui/react";
+import type { ReactNode } from "react";
+
+import { CustomIcon } from "../../icon";
+import type { HexAddr20, Option } from "lib/types";
+import { EvmVerifyInfo } from "lib/services/types";
+import { EvmVerifyRequestInfo } from "./EvmVerifyRequestInfo";
+import { EvmVerifyAlert } from "./EvmVerifyAlert";
+import { EvmVerifyProcess } from "./EvmVerifyProcess";
+
+interface EvmVerifyStatusModalProps {
+ contractAddress: HexAddr20;
+ evmVerifyInfo: Option;
+ isOpen: boolean;
+ onClose: () => void;
+}
+
+export const EvmVerifyStatusModal = ({
+ contractAddress,
+ evmVerifyInfo,
+ isOpen,
+ onClose,
+}: EvmVerifyStatusModalProps) => (
+
+
+
+
+
+
+
+ Contract Verification Status
+
+
+
+
+
+ {evmVerifyInfo?.errorMessage && (
+
+ )}
+
+
+
+ {evmVerifyInfo && }
+
+
+
+
+
+);
+
+interface EvmVerifyStatusModalTriggerProps
+ extends Pick {
+ triggerElement: ReactNode;
+}
+
+export const EvmVerifyStatusModalWithTrigger = ({
+ triggerElement,
+ contractAddress,
+ evmVerifyInfo,
+}: EvmVerifyStatusModalTriggerProps) => {
+ const { isOpen, onClose, onOpen } = useDisclosure();
+
+ return (
+ <>
+ {
+ e.stopPropagation();
+ onOpen();
+ }}
+ >
+ {triggerElement}
+
+
+ >
+ );
+};
diff --git a/src/lib/components/modal/evm-verify-status/utils.ts b/src/lib/components/modal/evm-verify-status/utils.ts
new file mode 100644
index 000000000..82f7322a6
--- /dev/null
+++ b/src/lib/components/modal/evm-verify-status/utils.ts
@@ -0,0 +1,76 @@
+import { EvmVerifyInfo } from "lib/services/types";
+import type { Option } from "lib/types";
+
+enum ProcessStepState {
+ PENDING = "Pending",
+ IN_PROGRESS = "In Progress",
+ COMPLETED = "Completed",
+ FAILED = "Failed",
+}
+
+interface ProcessStep {
+ label: string;
+ state: ProcessStepState;
+ timestamp?: Date;
+ errorMsg?: string;
+}
+
+const getProcessStep = (
+ date: Option,
+ errorMsg: Option,
+ prevStepState?: ProcessStepState
+) => {
+ if (
+ prevStepState === ProcessStepState.FAILED ||
+ prevStepState === ProcessStepState.PENDING ||
+ prevStepState === ProcessStepState.IN_PROGRESS
+ )
+ return {
+ state: ProcessStepState.PENDING,
+ };
+
+ if (date)
+ return {
+ timestamp: date,
+ state: ProcessStepState.COMPLETED,
+ };
+
+ if (errorMsg)
+ return {
+ state: ProcessStepState.FAILED,
+ errorMsg,
+ };
+
+ return {
+ state: ProcessStepState.IN_PROGRESS,
+ };
+};
+
+export const getProcessSteps = (
+ evmVerifyInfo: EvmVerifyInfo
+): ProcessStep[] => {
+ const step1 = {
+ label: "Submitted Source Code",
+ ...getProcessStep(
+ evmVerifyInfo.submittedTimestamp,
+ evmVerifyInfo.errorMessage
+ ),
+ };
+ const step2 = {
+ label: "Verifying",
+ ...getProcessStep(
+ evmVerifyInfo.verifiedTimestamp,
+ evmVerifyInfo.errorMessage,
+ step1.state
+ ),
+ };
+ const step3 = {
+ label: "Verification Completed",
+ state:
+ step2.state === ProcessStepState.COMPLETED
+ ? ProcessStepState.COMPLETED
+ : ProcessStepState.PENDING,
+ };
+
+ return [step1, step2, step3];
+};
diff --git a/src/lib/pages/evm-contract-details/components/EvmContractDetailsOverview.tsx b/src/lib/pages/evm-contract-details/components/EvmContractDetailsOverview.tsx
index 6e484da65..1d528ed3a 100644
--- a/src/lib/pages/evm-contract-details/components/EvmContractDetailsOverview.tsx
+++ b/src/lib/pages/evm-contract-details/components/EvmContractDetailsOverview.tsx
@@ -3,7 +3,7 @@ import { Flex, Grid, Spinner, Stack, Text } from "@chakra-ui/react";
import type { TxsTabIndex } from "../types";
import { useCelatoneApp, useMobile } from "lib/app-provider";
import { AssetsSection } from "lib/components/asset";
-import { NotVerifiedDetails } from "lib/components/evm-verify-section";
+import { EvmVerifySection } from "lib/components/evm-verify-section";
import { ExplorerLink } from "lib/components/ExplorerLink";
import { LabelText } from "lib/components/LabelText";
import { useFormatAddresses } from "lib/hooks/useFormatAddresses";
@@ -17,6 +17,7 @@ import type {
import { dateFromNow, formatEvmTxHash, formatUTC } from "lib/utils";
import { EvmContractDetailsTxs } from "./EvmContractDetailsTxs";
+import { useEvmVerifyInfo } from "lib/services/verification/evm";
interface EvmContractDetailsOverviewProps {
contractAddressBech: BechAddr20;
@@ -48,11 +49,14 @@ export const EvmContractDetailsOverview = ({
const { currentChainId } = useCelatoneApp();
const formatAddresses = useFormatAddresses();
const isMobile = useMobile();
+ const { data: evmVerifyInfo } = useEvmVerifyInfo(contractAddressHex);
return (
- {/* // TODO: Support all status */}
-
+
;
}
-export const EvmContractDetailsContract = ({
+export const EvmContractDetailsContractInfo = ({
contractAddress,
byteCode,
deployedByteCode,
evmVerifyInfo,
-}: EvmContractDetailsContractProps) => {
+}: EvmContractDetailsContractInfoProps) => {
+ const isVerified = evmVerifyInfo?.isVerified;
const [currentTab, setCurrentTab] = useState(
- evmVerifyInfo
- ? EvmContractDetailsContractTabs.Code
- : EvmContractDetailsContractTabs.ByteCode
+ isVerified
+ ? EvmContractDetailsContractInfoTabs.Code
+ : EvmContractDetailsContractInfoTabs.ByteCode
);
return (
- {/* // TODO: Support all status */}
-
- {evmVerifyInfo && (
+
+ {isVerified ? (
<>
- {currentTab === EvmContractDetailsContractTabs.Code && (
+ {currentTab === EvmContractDetailsContractInfoTabs.Code && (
)}
- {currentTab === EvmContractDetailsContractTabs.Compiler && (
+ {currentTab === EvmContractDetailsContractInfoTabs.Compiler && (
)}
- {currentTab === EvmContractDetailsContractTabs.Abi && (
-
+ {currentTab === EvmContractDetailsContractInfoTabs.Abi && (
+
+ )}
+ {currentTab === EvmContractDetailsContractInfoTabs.ByteCode && (
+
)}
>
- )}
- {currentTab === EvmContractDetailsContractTabs.ByteCode && (
+ ) : (
Contract
+
+ Read/Write
+
- {/* TODO: move to a proper location */}
-
-
+
+
+
diff --git a/src/lib/pages/evm-contract-details/types.ts b/src/lib/pages/evm-contract-details/types.ts
index 36435bc75..f0c18c0e5 100644
--- a/src/lib/pages/evm-contract-details/types.ts
+++ b/src/lib/pages/evm-contract-details/types.ts
@@ -5,6 +5,7 @@ import { zHexAddr20 } from "lib/types";
export enum TabIndex {
Overview = "overview",
Contract = "contract",
+ ReadWrite = "read-write",
Assets = "assets",
Transactions = "transactions",
}
@@ -16,7 +17,7 @@ export enum InteractTabsIndex {
WriteProxy = "write-proxy",
}
-export enum EvmContractDetailsContractTabs {
+export enum EvmContractDetailsContractInfoTabs {
Code = "Code",
Compiler = "Compiler",
Abi = "ABI",
diff --git a/src/lib/pages/evm-contract-verify/components/EvmContractVerifyFooter.tsx b/src/lib/pages/evm-contract-verify/components/EvmContractVerifyFooter.tsx
index 3b689048d..606a926b2 100644
--- a/src/lib/pages/evm-contract-verify/components/EvmContractVerifyFooter.tsx
+++ b/src/lib/pages/evm-contract-verify/components/EvmContractVerifyFooter.tsx
@@ -1,11 +1,8 @@
-import { CustomIcon } from "lib/components/icon";
import { FooterCta } from "lib/components/layouts";
interface EvmContractFooterProps {
handleNext: () => void;
handlePrevious: () => void;
- hasNext: boolean;
- hasPrevious: boolean;
isDisabled: boolean;
actionLabel: string;
}
@@ -13,8 +10,6 @@ interface EvmContractFooterProps {
export const EvmContractFooter = ({
handleNext,
handlePrevious,
- hasNext,
- hasPrevious,
isDisabled,
actionLabel,
}: EvmContractFooterProps) => (
@@ -22,17 +17,11 @@ export const EvmContractFooter = ({
cancelButton={{
onClick: handlePrevious,
variant: "outline-primary",
- leftIcon: hasPrevious ? (
-
- ) : undefined,
}}
- cancelLabel={hasPrevious ? "Previous" : "Cancel"}
+ cancelLabel="Cancel"
actionButton={{
onClick: handleNext,
isDisabled,
- rightIcon: hasNext ? (
-
- ) : undefined,
}}
actionLabel={actionLabel}
sx={{
diff --git a/src/lib/pages/evm-contract-verify/helpers.ts b/src/lib/pages/evm-contract-verify/helpers.ts
index e9a078833..78793c1f5 100644
--- a/src/lib/pages/evm-contract-verify/helpers.ts
+++ b/src/lib/pages/evm-contract-verify/helpers.ts
@@ -1,10 +1,7 @@
import { HexAddr20, Option, zHexAddr20 } from "lib/types";
import { EvmContractVerifyForm } from "./types";
-import {
- EvmProgrammingLanguage,
- EvmVerifyConfig,
- EVMVerifyLicenseType,
-} from "lib/services/types";
+import { EvmProgrammingLanguage, EvmVerifyConfig } from "lib/services/types";
+import { getLicenseTypeLabel } from "lib/utils";
const CONSTRUCTOR_ARGS_DEFAULT_VALUE = {
enabled: false,
@@ -70,41 +67,6 @@ export const getEvmContractVerifyFormDefaultValue = (
},
});
-const getLicenseTypeLabel = (license: EVMVerifyLicenseType) => {
- switch (license) {
- case EVMVerifyLicenseType.None:
- return "1. No License (None)";
- case EVMVerifyLicenseType.Unlicense:
- return "2. The Unlicense (Unlicense)";
- case EVMVerifyLicenseType.MIT:
- return "3. MIT License (MIT)";
- case EVMVerifyLicenseType.GNUGPLv2:
- return "4. GNU General Public License v2.0 (GNU GPLv2)";
- case EVMVerifyLicenseType.GNUGPLv3:
- return "5. GNU General Public License v3.0 (GNU GPLv3)";
- case EVMVerifyLicenseType.GNULGPLv2_1:
- return "6. GNU Lesser General Public License v2.1 (GNU LGPLv2.1)";
- case EVMVerifyLicenseType.GNULGPLv3:
- return "7. GNU Lesser General Public License v3.0 (GNU LGPLv3)";
- case EVMVerifyLicenseType.BSD2Clause:
- return `8. BSD 2-Clause "Simplified" license (BSD 2-Clause)`;
- case EVMVerifyLicenseType.BSD3Clause:
- return `9. BSD 3-Clause "New" or "Revised" license (BSD 3-Clause)`;
- case EVMVerifyLicenseType.MPL2_0:
- return "10. Mozilla Public License 2.0 (MPL 2.0)";
- case EVMVerifyLicenseType.OSL3_0:
- return "11. Open Software License 3.0 (OSL 3.0)";
- case EVMVerifyLicenseType.Apache2_0:
- return "12. Apache 2.0 (Apache 2.0)";
- case EVMVerifyLicenseType.GNUAGPLv3:
- return "13. GNU Affero General Public License (GNU AGPLv3)";
- case EVMVerifyLicenseType.BSL1_1:
- return "14. Business Source License (BSL 1.1)";
- default:
- return "";
- }
-};
-
export const formatEvmOptions = (values: string[]) =>
values.map((value) => ({
label: value,
@@ -112,8 +74,8 @@ export const formatEvmOptions = (values: string[]) =>
}));
export const getLicenseTypeOptions = (evmVerifyConfig: EvmVerifyConfig) =>
- evmVerifyConfig.licenseType.map((license) => ({
- label: getLicenseTypeLabel(license),
+ evmVerifyConfig.licenseType.map((license, index) => ({
+ label: `${index + 1}. ${getLicenseTypeLabel(license)}`,
value: license,
}));
diff --git a/src/lib/pages/evm-contract-verify/index.tsx b/src/lib/pages/evm-contract-verify/index.tsx
index 338f285ae..275d2e62e 100644
--- a/src/lib/pages/evm-contract-verify/index.tsx
+++ b/src/lib/pages/evm-contract-verify/index.tsx
@@ -12,10 +12,10 @@ import {
Heading,
Stack,
Text,
+ useDisclosure,
} from "@chakra-ui/react";
import { EvmContractVerifyTop } from "./components/EvmContractVerifyTop";
import { ContractLicenseInfoAccordion } from "./components/ContractLicenseInfoAccordion";
-import { useStepper } from "lib/hooks";
import { EvmContractFooter } from "./components/EvmContractVerifyFooter";
import { ControllerInput, SelectInput } from "lib/components/forms";
import { useForm } from "react-hook-form";
@@ -40,9 +40,13 @@ import { HarthatInfoAccordion } from "./components/HardhatInfoAccordion";
import { FoundryInfoAccordion } from "./components/FoundryInfoAccordion";
import { ErrorFetching, InvalidState } from "lib/components/state";
import { HexAddr20, Option } from "lib/types";
-import { useEvmVerifyConfig } from "lib/services/verification/evm";
+import {
+ useEvmVerifyConfig,
+ useEvmVerifyInfo,
+} from "lib/services/verification/evm";
import { Loading } from "lib/components/Loading";
import { EvmProgrammingLanguage, EvmVerifyConfig } from "lib/services/types";
+import { EvmVerifyStatusModal } from "lib/components/modal/evm-verify-status";
interface EvmContractVerifyBodyProps {
contractAddress: Option;
@@ -79,20 +83,6 @@ export const EvmContractVerifyBody = ({
const { licenseType, contractAddress, language, compilerVersion, option } =
watch();
- const { handleNext, handlePrevious, hasNext, hasPrevious } = useStepper(
- 1,
- () => {
- if (
- option === VerifyOptions.SolidityHardhat ||
- option === VerifyOptions.SolidityFoundry
- ) {
- alert("Open Verification Status Modal");
- } else {
- alert("Submit!");
- }
- }
- );
-
const { licenseTypeOptions, compilerVersionOptions } = useMemo(
() => ({
licenseTypeOptions: getLicenseTypeOptions(evmVerifyConfig),
@@ -104,8 +94,21 @@ export const EvmContractVerifyBody = ({
[evmVerifyConfig, language]
);
+ const { data: evmVerifyInfo } = useEvmVerifyInfo(contractAddress);
+ const { isOpen, onOpen, onClose } = useDisclosure();
+
+ const handleSubmit = () => {
+ if (
+ option === VerifyOptions.SolidityHardhat ||
+ option === VerifyOptions.SolidityFoundry
+ ) {
+ onOpen();
+ } else {
+ alert("Submit!");
+ }
+ };
+
const isFormDisabled = () => {
- // TODO: Update the validation
return false;
};
@@ -262,12 +265,16 @@ export const EvmContractVerifyBody = ({
? "View Verification Status"
: "Verify & Publish Contract"
}
- handleNext={handleNext}
- handlePrevious={handlePrevious}
- hasNext={hasNext}
- hasPrevious={hasPrevious}
+ handleNext={handleSubmit}
+ handlePrevious={router.back}
isDisabled={isFormDisabled()}
/>
+
>
)}
>
diff --git a/src/lib/services/types/verification/evm.ts b/src/lib/services/types/verification/evm.ts
index f9da5a816..c58511b06 100644
--- a/src/lib/services/types/verification/evm.ts
+++ b/src/lib/services/types/verification/evm.ts
@@ -8,7 +8,7 @@ export enum EvmProgrammingLanguage {
Vyper = "Vyper",
}
-export enum EVMVerifyLicenseType {
+export enum EvmVerifyLicenseType {
None = "none",
Unlicense = "unlicense",
MIT = "mit",
@@ -27,7 +27,7 @@ export enum EVMVerifyLicenseType {
export const zEvmVerifyConfig = z
.object({
- license_type: z.array(z.nativeEnum(EVMVerifyLicenseType)),
+ license_type: z.array(z.nativeEnum(EvmVerifyLicenseType)),
solidity_compiler_versions: z.array(z.string()),
solidity_evm_versions: z.array(z.string()),
vyper_compiler_versions: z.array(z.string()),
@@ -50,26 +50,28 @@ export type EvmVerifyInfoSourceFile = z.infer;
export const zEvmVerifyInfo = z
.object({
guid: z.string().uuid(),
- license: z.nativeEnum(EVMVerifyLicenseType),
+ license: z.nativeEnum(EvmVerifyLicenseType),
language: z.nativeEnum(EvmProgrammingLanguage),
chain_id: z.string(),
address: zHexAddr20,
- contract_name: z.string(),
- contract_path: z.string(),
+ contract_name: z.string().optional(),
+ contract_path: z.string().optional(),
compiler_version: z.string(),
evm_version: z.string(),
optimizer: z.string(),
constructor_arguments: z.string(),
- abi: z.string(),
+ abi: z.string().optional(),
bytecode_type: z.string(),
- verified_timestamp: zUtcDate,
+ verified_timestamp: zUtcDate.optional(),
submitted_timestamp: zUtcDate,
+ error_message: z.string().optional(),
// libraries: z.array() // TODO: Recheck
settings: z.string(),
source_files: z.array(zEvmVerifyInfoSourceFile),
})
.transform(({ abi, ...rest }) => ({
- abi: JSON.parse(abi) as JsonFragment[],
+ abi: abi ? (JSON.parse(abi) as JsonFragment[]) : undefined,
...snakeToCamel(rest),
+ isVerified: !!rest.verified_timestamp,
}));
export type EvmVerifyInfo = z.infer;
diff --git a/src/lib/utils/verification/evm.ts b/src/lib/utils/verification/evm.ts
new file mode 100644
index 000000000..a0984cd17
--- /dev/null
+++ b/src/lib/utils/verification/evm.ts
@@ -0,0 +1,36 @@
+import { EvmVerifyLicenseType } from "lib/services/types";
+
+export const getLicenseTypeLabel = (license: EvmVerifyLicenseType) => {
+ switch (license) {
+ case EvmVerifyLicenseType.None:
+ return "No License (None)";
+ case EvmVerifyLicenseType.Unlicense:
+ return "The Unlicense (Unlicense)";
+ case EvmVerifyLicenseType.MIT:
+ return "MIT License (MIT)";
+ case EvmVerifyLicenseType.GNUGPLv2:
+ return "GNU General Public License v2.0 (GNU GPLv2)";
+ case EvmVerifyLicenseType.GNUGPLv3:
+ return "GNU General Public License v3.0 (GNU GPLv3)";
+ case EvmVerifyLicenseType.GNULGPLv2_1:
+ return "GNU Lesser General Public License v2.1 (GNU LGPLv2.1)";
+ case EvmVerifyLicenseType.GNULGPLv3:
+ return "GNU Lesser General Public License v3.0 (GNU LGPLv3)";
+ case EvmVerifyLicenseType.BSD2Clause:
+ return `BSD 2-Clause "Simplified" license (BSD 2-Clause)`;
+ case EvmVerifyLicenseType.BSD3Clause:
+ return `BSD 3-Clause "New" or "Revised" license (BSD 3-Clause)`;
+ case EvmVerifyLicenseType.MPL2_0:
+ return "Mozilla Public License 2.0 (MPL 2.0)";
+ case EvmVerifyLicenseType.OSL3_0:
+ return "Open Software License 3.0 (OSL 3.0)";
+ case EvmVerifyLicenseType.Apache2_0:
+ return "Apache 2.0 (Apache 2.0)";
+ case EvmVerifyLicenseType.GNUAGPLv3:
+ return "GNU Affero General Public License (GNU AGPLv3)";
+ case EvmVerifyLicenseType.BSL1_1:
+ return "Business Source License (BSL 1.1)";
+ default:
+ return "";
+ }
+};
diff --git a/src/lib/utils/verification/index.ts b/src/lib/utils/verification/index.ts
index e4638e151..7e01ce292 100644
--- a/src/lib/utils/verification/index.ts
+++ b/src/lib/utils/verification/index.ts
@@ -1 +1,2 @@
export * from "./wasm";
+export * from "./evm";