Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/evm contract verfied abi #1206

Merged
merged 6 commits into from
Jan 23, 2025
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#1206](https://github.com/alleslabs/celatone-frontend/pull/1206) Add EVM contract details abi
- [#1204](https://github.com/alleslabs/celatone-frontend/pull/1204) Add EVM contract details deployed bytecode
- [#1203](https://github.com/alleslabs/celatone-frontend/pull/1203) Fetch EVM verify config from API, and wire up to UIs as initial values
- [#1202](https://github.com/alleslabs/celatone-frontend/pull/1202) Add EVM contract interaction form
Expand Down
1 change: 1 addition & 0 deletions src/lib/app-provider/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export enum CELATONE_QUERY_KEYS {
MOVE_VERIFY_INFOS_BY_ADDRESS = "CELATONE_QUERY_MOVE_VERIFY_INFOS_BY_ADDRESS",
MOVE_VERIFY_TASK_BY_TASK_ID = "CELATONE_QUERY_MOVE_VERIFY_TASK_BY_TASK_ID",
EVM_VERIFY_CONFIG = "CELATONE_QUERY_EVM_VERIFY_CONFIG",
EVM_VERIFY_INFO = "CELATONE_QUERY_EVM_VERIFY_INFO",
// CHAIN CONFIGS
CHAIN_CONFIGS = "CELATONE_QUERY_CHAIN_CONFIGS",
// DOCKER
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Heading, Stack } from "@chakra-ui/react";
import JsonReadOnly from "lib/components/json/JsonReadOnly";
import { jsonPrettify } from "lib/utils";

interface ContractAbiProps {
abi: string;
}

export const ContractAbi = ({ abi }: ContractAbiProps) => (
<Stack gap={4}>
<Heading as="h6" variant="h7">
Contract ABI
</Heading>
<JsonReadOnly text={jsonPrettify(abi)} />
evilpeach marked this conversation as resolved.
Show resolved Hide resolved
</Stack>
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { EvmContractDetailsContractTabs } from "../../types";
import { useState } from "react";
import { TypeSwitch } from "lib/components/TypeSwitch";
import { ContractByteCode, ContractByteCodeProps } from "./ContractByteCode";
import { ContractAbi } from "./ContractAbi";
import { useEvmVerifyInfo } from "lib/services/verification/evm";
import { ErrorFetching } from "lib/components/state";

interface EvmContractDetailsContractProps extends ContractByteCodeProps {
contractAddress: HexAddr20;
Expand All @@ -15,10 +18,14 @@ export const EvmContractDetailsContract = ({
byteCode,
deployedByteCode,
}: EvmContractDetailsContractProps) => {
const { data } = useEvmVerifyInfo(contractAddress);
evilpeach marked this conversation as resolved.
Show resolved Hide resolved

const [currentTab, setCurrentTab] = useState(
EvmContractDetailsContractTabs.ByteCode
EvmContractDetailsContractTabs.Abi
);

if (!data) return <ErrorFetching dataName="evm contract information" />;

return (
<Stack gap={8}>
{/* // TODO: Support all status */}
Expand All @@ -30,6 +37,9 @@ export const EvmContractDetailsContract = ({
currentTab={currentTab}
/>
</Flex>
{currentTab === EvmContractDetailsContractTabs.Abi && (
<ContractAbi abi={data.abi} />
)}
evilpeach marked this conversation as resolved.
Show resolved Hide resolved
{currentTab === EvmContractDetailsContractTabs.ByteCode && (
<ContractByteCode
byteCode={byteCode}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Grid, Heading, Radio, RadioGroup, Stack } from "@chakra-ui/react";
import { Control, useController, useWatch } from "react-hook-form";
import {
EvmContractVerifyForm,
EvmProgrammingLanguage,
VerifyOptions,
} from "../types";
import { EvmContractVerifyForm, VerifyOptions } from "../types";
import { EvmProgrammingLanguage } from "lib/services/types";

interface EvmContractVerifyVyperProps {
control: Control<EvmContractVerifyForm>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Grid, Heading, Stack, Text } from "@chakra-ui/react";
import { SelectInput } from "lib/components/forms";
import { EvmVerifyConfig } from "lib/services/types";
import { EvmProgrammingLanguage, EvmVerifyConfig } from "lib/services/types";
import { useMemo } from "react";
import {
Control,
Expand All @@ -9,7 +9,6 @@ import {
useController,
useWatch,
} from "react-hook-form";
import { EvmProgrammingLanguage } from "../types";
import { formatEvmOptions } from "../helpers";

interface EvmVersionToTargetProps<T extends FieldValues> {
Expand Down
8 changes: 6 additions & 2 deletions src/lib/pages/evm-contract-verify/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { HexAddr20, Option, zHexAddr20 } from "lib/types";
import { EvmContractVerifyForm, EvmProgrammingLanguage } from "./types";
import { EvmVerifyConfig, EVMVerifyLicenseType } from "lib/services/types";
import { EvmContractVerifyForm } from "./types";
import {
EvmProgrammingLanguage,
EvmVerifyConfig,
EVMVerifyLicenseType,
} from "lib/services/types";

const CONSTRUCTOR_ARGS_DEFAULT_VALUE = {
enabled: false,
Expand Down
3 changes: 1 addition & 2 deletions src/lib/pages/evm-contract-verify/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { ControllerInput, SelectInput } from "lib/components/forms";
import { useForm } from "react-hook-form";
import {
EvmContractVerifyForm,
EvmProgrammingLanguage,
VerifyOptions,
zEvmContractVerifyForm,
zEvmContractVerifyQueryParams,
Expand All @@ -43,7 +42,7 @@ import { ErrorFetching, InvalidState } from "lib/components/state";
import { HexAddr20, Option } from "lib/types";
import { useEvmVerifyConfig } from "lib/services/verification/evm";
import { Loading } from "lib/components/Loading";
import { EvmVerifyConfig } from "lib/services/types";
import { EvmProgrammingLanguage, EvmVerifyConfig } from "lib/services/types";

interface EvmContractVerifyBodyProps {
contractAddress: Option<HexAddr20>;
Expand Down
6 changes: 1 addition & 5 deletions src/lib/pages/evm-contract-verify/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { EvmProgrammingLanguage } from "lib/services/types";
import { zHexAddr20 } from "lib/types";
import { isHex20Bytes } from "lib/utils";
import { z, ZodIssueCode } from "zod";

export enum EvmProgrammingLanguage {
Solidity = "solidity",
Vyper = "vyper",
}

export enum VerifyOptions {
VyperUploadFile = "vyper-upload-file",
VyperContractCode = "vyper-contract-code",
Expand Down
39 changes: 39 additions & 0 deletions src/lib/services/types/verification/evm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { zHexAddr20, zUtcDate } from "lib/types";
import { snakeToCamel } from "lib/utils";
import { z } from "zod";

export enum EvmProgrammingLanguage {
Solidity = "Solidity",
Vyper = "Vyper",
}

export enum EVMVerifyLicenseType {
None = "none",
Unlicense = "unlicense",
Expand Down Expand Up @@ -28,3 +34,36 @@ export const zEvmVerifyConfig = z
})
.transform(snakeToCamel);
export type EvmVerifyConfig = z.infer<typeof zEvmVerifyConfig>;

const zEvmVerifyInfoSourceFile = z
.object({
source_path: z.string(),
evm_source_file: z.object({
hash: z.string(),
content: z.string(),
}),
})
.transform(snakeToCamel);

export const zEvmVerifyInfo = z
.object({
guid: z.string().uuid(),
license: z.nativeEnum(EVMVerifyLicenseType),
language: z.nativeEnum(EvmProgrammingLanguage),
chain_id: z.string(),
address: zHexAddr20,
contract_name: z.string(),
contract_path: z.string(),
compiler_version: z.string(),
evm_version: z.string(),
optimizer: z.string(),
constructor_arguments: z.string(),
abi: z.string(),
bytecode_type: z.string(),
verified_timestamp: zUtcDate,
submitted_timestamp: zUtcDate,
// libraries: z.array() // TODO: Recheck
settings: z.string(),
source_files: z.array(zEvmVerifyInfoSourceFile),
})
.transform(snakeToCamel);
17 changes: 16 additions & 1 deletion src/lib/services/verification/evm/api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import axios from "axios";
import { CELATONE_VERIFICATION_API } from "env";
import { zEvmVerifyConfig } from "lib/services/types";
import { zEvmVerifyConfig, zEvmVerifyInfo } from "lib/services/types";
import { HexAddr20 } from "lib/types";

export const getEvmVerifyConfig = async () =>
axios
.get(`${CELATONE_VERIFICATION_API}/evm/verification/config`)
.then(({ data }) => zEvmVerifyConfig.parse(data));

export const getEvmVerifyInfo = async (
chainId: string,
contractAddress: HexAddr20
) => {
return axios
.get(`${CELATONE_VERIFICATION_API}/evm/verification/info`, {
params: {
chain_id: chainId,
address: contractAddress,
},
})
.then(({ data }) => zEvmVerifyInfo.parse(data));
};
evilpeach marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 16 additions & 1 deletion src/lib/services/verification/evm/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { CELATONE_QUERY_KEYS } from "lib/app-provider/env";
import { getEvmVerifyConfig } from "./api";
import { getEvmVerifyConfig, getEvmVerifyInfo } from "./api";
import { HexAddr20 } from "lib/types";
import { useCurrentChain } from "lib/app-provider";

export const useEvmVerifyConfig = () =>
useQuery({
Expand All @@ -11,3 +13,16 @@ export const useEvmVerifyConfig = () =>
staleTime: Infinity,
retryOnMount: false,
});

export const useEvmVerifyInfo = (contractAddress: HexAddr20) => {
const { chainId } = useCurrentChain();

return useQuery({
queryKey: [CELATONE_QUERY_KEYS.EVM_VERIFY_INFO, chainId, contractAddress],
queryFn: () => getEvmVerifyInfo(chainId, contractAddress),
refetchOnWindowFocus: false,
retry: 1,
staleTime: Infinity,
retryOnMount: false,
});
};
Loading