From dcfff8bacfc55ab22188c9117738e833cdd34b10 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 1 May 2024 14:58:29 +0700 Subject: [PATCH 01/10] feat: rename modules fields --- CHANGELOG.md | 1 + src/lib/app-provider/env.ts | 3 +- .../components/module/FunctionDetailCard.tsx | 3 +- src/lib/components/module/ModuleCard.tsx | 3 +- .../components/table/modules/ModulesTable.tsx | 4 +- .../table/modules/ModulesTableMobileCard.tsx | 15 +- .../table/modules/ModulesTableRow.tsx | 43 +++-- .../components/modules/ModuleLists.tsx | 3 +- .../components/modules/ModuleListsBody.tsx | 3 +- src/lib/pages/account-details/index.tsx | 12 +- .../interact/component/FunctionSelectBody.tsx | 3 +- .../component/FunctionSelectPanel.tsx | 3 +- .../component/drawer/ModuleSelectDrawer.tsx | 13 +- .../drawer/body/ModuleFunctionBody.tsx | 3 +- .../drawer/body/ModuleSelectMainBody.tsx | 3 +- .../drawer/selector/ModuleSelectorInput.tsx | 48 ++--- .../pages/interact/component/drawer/types.ts | 8 +- src/lib/pages/interact/data.ts | 55 ++++++ src/lib/pages/interact/index.tsx | 31 ++-- .../module-details/components/ModuleInfo.tsx | 2 +- .../components/ModuleStructs.tsx | 2 +- .../module-details/components/ModuleTop.tsx | 13 +- .../components/module-fns/ModuleFunctions.tsx | 3 +- src/lib/pages/module-details/index.tsx | 167 +++++++----------- src/lib/pages/module-details/types.ts | 20 +++ .../components/MyPublishedModulesTable.tsx | 26 +-- src/lib/services/move/module.ts | 128 ++++++++------ src/lib/services/move/moduleService.ts | 102 ++++------- src/lib/services/searchService.ts | 22 +-- src/lib/types/move/abi.ts | 6 - src/lib/types/move/module.ts | 31 +++- 31 files changed, 397 insertions(+), 382 deletions(-) create mode 100644 src/lib/pages/interact/data.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index e0a56ffb5..5437d15a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#905](https://github.com/alleslabs/celatone-frontend/pull/905) Refactor module related component for better readability - [#900](https://github.com/alleslabs/celatone-frontend/pull/900) Refactor module details info - [#899](https://github.com/alleslabs/celatone-frontend/pull/899) Refactor module details APIs - [#866](https://github.com/alleslabs/celatone-frontend/pull/866) Update upload code CTA to sticky bar diff --git a/src/lib/app-provider/env.ts b/src/lib/app-provider/env.ts index 9042fd08f..d28b807f0 100644 --- a/src/lib/app-provider/env.ts +++ b/src/lib/app-provider/env.ts @@ -98,7 +98,9 @@ export enum CELATONE_QUERY_KEYS { // MOVE MOVE_POOL_INFOS = "CELATONE_QUERY_MOVE_POOL_INFOS", // MODULES + MODULE_DATA = "CELATONE_QUERY_MODULE_DATA", MODULES_BY_ADDRESS = "CELATONE_QUERY_MODULES_BY_ADDRESS", + ACCOUNT_MODULE = "CELATONE_QUERY_ACCOUNT_MODULE", ACCOUNT_MODULES = "CELATONE_QUERY_ACCOUNT_MODULES", MODULES = "CELATONE_QUERY_MODULES", MODULE_VERIFICATION = "CELATONE_QUERY_MODULE_VERIFICATION", @@ -109,7 +111,6 @@ export enum CELATONE_QUERY_KEYS { MODULE_HISTORIES = "CELATONE_QUERY_MODULE_HISTORIES", MODULE_PROPOSALS = "CELATONE_QUERY_MODULE_PROPOSALS", SCRIPT_DECODE = "CELATONE_QUERY_SCRIPT_DECODE", - MODULE_INFO = "CELATONE_QUERY_MODULE_INFO", // RESOURCE RESOURCES_BY_ADDRESS = "CELATONE_QUERY_RESOURCES_BY_ADDRESS", // NFTS diff --git a/src/lib/components/module/FunctionDetailCard.tsx b/src/lib/components/module/FunctionDetailCard.tsx index 49d14374b..d4915bdd6 100644 --- a/src/lib/components/module/FunctionDetailCard.tsx +++ b/src/lib/components/module/FunctionDetailCard.tsx @@ -15,8 +15,7 @@ import { LabelText } from "../LabelText"; import { Tooltip } from "../Tooltip"; import { AmpEvent, track, trackUseExpand } from "lib/amplitude"; import { useInternalNavigate, useMobile } from "lib/app-provider"; -import type { IndexedModule } from "lib/services/move/moduleService"; -import type { ExposedFunction } from "lib/types"; +import type { ExposedFunction, IndexedModule } from "lib/types"; import { checkAvailability, getFirstQueryParam, diff --git a/src/lib/components/module/ModuleCard.tsx b/src/lib/components/module/ModuleCard.tsx index 55d86419a..c78d53f55 100644 --- a/src/lib/components/module/ModuleCard.tsx +++ b/src/lib/components/module/ModuleCard.tsx @@ -5,9 +5,8 @@ import { useMemo } from "react"; import { AppLink } from "../AppLink"; import { CustomIcon } from "../icon"; import { AmpEvent, track } from "lib/amplitude"; -import type { IndexedModule } from "lib/services/move/moduleService"; import { useVerifyModule } from "lib/services/move/moduleService"; -import type { BechAddr, Option } from "lib/types"; +import type { BechAddr, IndexedModule, Option } from "lib/types"; import { CountBadge } from "./CountBadge"; diff --git a/src/lib/components/table/modules/ModulesTable.tsx b/src/lib/components/table/modules/ModulesTable.tsx index c1ea6892a..13cdb0a75 100644 --- a/src/lib/components/table/modules/ModulesTable.tsx +++ b/src/lib/components/table/modules/ModulesTable.tsx @@ -32,7 +32,7 @@ export const ModulesTable = ({ return isMobile ? ( {modules.map((module) => ( - + ))} ) : ( @@ -43,7 +43,7 @@ export const ModulesTable = ({ /> {modules.map((module) => ( { const navigate = useInternalNavigate(); - const hex = unpadHexAddress(bech32AddressToHex(moduleInfo.address)); return ( @@ -31,14 +25,17 @@ export const ModulesTableMobileCard = ({ pathname: "/modules/[address]/[moduleName]", query: { address: moduleInfo.address, - moduleName: moduleInfo.name, + moduleName: moduleInfo.moduleName, }, }) } topContent={ - + } middleContent={ diff --git a/src/lib/components/table/modules/ModulesTableRow.tsx b/src/lib/components/table/modules/ModulesTableRow.tsx index 76aba41d5..b1e7da4a0 100644 --- a/src/lib/components/table/modules/ModulesTableRow.tsx +++ b/src/lib/components/table/modules/ModulesTableRow.tsx @@ -5,13 +5,9 @@ import { AmpEvent, track } from "lib/amplitude"; import { useInternalNavigate } from "lib/app-provider"; import { ExplorerLink } from "lib/components/ExplorerLink"; import { CountBadge } from "lib/components/module"; +import { useFormatAddresses } from "lib/hooks/useFormatAddresses"; import type { ModuleInfo } from "lib/types"; -import { - bech32AddressToHex, - dateFromNow, - formatUTC, - unpadHexAddress, -} from "lib/utils"; +import { dateFromNow, formatUTC } from "lib/utils"; import { ModulePathLink } from "./ModulePathLink"; @@ -27,7 +23,8 @@ export const ModulesTableRow = ({ isPublishedModules, }: ModulesTableRowProps) => { const navigate = useInternalNavigate(); - const hex = unpadHexAddress(bech32AddressToHex(moduleInfo.address)); + const formatAddresses = useFormatAddresses(); + const { address } = formatAddresses(moduleInfo.address); return ( @@ -41,37 +38,39 @@ export const ModulesTableRow = ({ navigate({ pathname: "/modules/[address]/[moduleName]", query: { - address: hex, - moduleName: moduleInfo.name, + address: moduleInfo.address, + moduleName: moduleInfo.moduleName, }, }) } > - + {isPublishedModules && ( - {moduleInfo.name} + {moduleInfo.moduleName} )} {isPublishedModules && ( - + )} - + {!isPublishedModules && moduleInfo.latestUpdated && ( @@ -94,8 +93,8 @@ export const ModulesTableRow = ({ navigate({ pathname: "/interact", query: { - address: hex, - moduleName: moduleInfo.name, + address: moduleInfo.address, + moduleName: moduleInfo.moduleName, functionType: "view", }, }); @@ -112,8 +111,8 @@ export const ModulesTableRow = ({ navigate({ pathname: "/interact", query: { - address: hex, - moduleName: moduleInfo.name, + address: moduleInfo.address, + moduleName: moduleInfo.moduleName, functionType: "execute", }, }); diff --git a/src/lib/pages/account-details/components/modules/ModuleLists.tsx b/src/lib/pages/account-details/components/modules/ModuleLists.tsx index 00326db1c..2e9b77680 100644 --- a/src/lib/pages/account-details/components/modules/ModuleLists.tsx +++ b/src/lib/pages/account-details/components/modules/ModuleLists.tsx @@ -4,8 +4,7 @@ import { useState } from "react"; import { useMobile } from "lib/app-provider"; import InputWithIcon from "lib/components/InputWithIcon"; import { MobileTitle, TableTitle, ViewMore } from "lib/components/table"; -import type { IndexedModule } from "lib/services/move/moduleService"; -import type { BechAddr, Option } from "lib/types"; +import type { BechAddr, IndexedModule, Option } from "lib/types"; import { ModuleListsBody } from "./ModuleListsBody"; diff --git a/src/lib/pages/account-details/components/modules/ModuleListsBody.tsx b/src/lib/pages/account-details/components/modules/ModuleListsBody.tsx index 3fd3b66dc..ef54d4d5f 100644 --- a/src/lib/pages/account-details/components/modules/ModuleListsBody.tsx +++ b/src/lib/pages/account-details/components/modules/ModuleListsBody.tsx @@ -4,8 +4,7 @@ import { useMemo } from "react"; import { Loading } from "lib/components/Loading"; import { ModuleCard } from "lib/components/module"; import { EmptyState, ErrorFetching } from "lib/components/state"; -import type { IndexedModule } from "lib/services/move/moduleService"; -import type { BechAddr, Option } from "lib/types"; +import type { BechAddr, IndexedModule, Option } from "lib/types"; interface ModuleListsBodyProps { address: BechAddr; diff --git a/src/lib/pages/account-details/index.tsx b/src/lib/pages/account-details/index.tsx index edfd88672..3d8597008 100644 --- a/src/lib/pages/account-details/index.tsx +++ b/src/lib/pages/account-details/index.tsx @@ -236,8 +236,8 @@ const AccountDetailsBody = ({ Resources Structs @@ -168,9 +140,10 @@ export const ModuleDetailsBody = ({ { @@ -218,11 +193,11 @@ export const ModuleDetailsBody = ({ @@ -247,7 +222,7 @@ export const ModuleDetailsBody = ({ /> - + { const router = useRouter(); - const addr = getFirstQueryParam(router.query.address); - const moduleName = getFirstQueryParam(router.query.moduleName); - - const { data: moduleInfo, isLoading: isModuleInfoLoading } = useModuleInfo( - addr as HexAddr, - moduleName - ); - const { data: moduleTableCounts, isLoading: isMoudleTableCountsLoading } = - useModuleTableCounts(moduleName, addr as HexAddr); - - if (!router.isReady || isModuleInfoLoading || isMoudleTableCountsLoading) - return ; + const validated = zModuleDetailsQueryParams.safeParse(router.query); return ( - {!moduleInfo || !moduleTableCounts ? ( + {!validated.success ? ( ) : ( - + )} ); diff --git a/src/lib/pages/module-details/types.ts b/src/lib/pages/module-details/types.ts index e74d21ebc..61a7c15e4 100644 --- a/src/lib/pages/module-details/types.ts +++ b/src/lib/pages/module-details/types.ts @@ -1,6 +1,26 @@ +import { z } from "zod"; + +import { zAddr } from "lib/types"; + export enum TabIndex { Overview = "overview", Function = "function", TxsHistories = "txs-histories", Structs = "structs", } + +export const zModuleDetailsQueryParams = z.object({ + address: zAddr, + moduleName: z.string(), + tab: z.union([ + z.nativeEnum(TabIndex), + z + .string() + .optional() + .transform(() => TabIndex.Overview), + ]), +}); + +export type ModuleDetailsQueryParams = z.infer< + typeof zModuleDetailsQueryParams +>; diff --git a/src/lib/pages/my-published-modules/components/MyPublishedModulesTable.tsx b/src/lib/pages/my-published-modules/components/MyPublishedModulesTable.tsx index 902ed8bb5..f5f75ba97 100644 --- a/src/lib/pages/my-published-modules/components/MyPublishedModulesTable.tsx +++ b/src/lib/pages/my-published-modules/components/MyPublishedModulesTable.tsx @@ -8,38 +8,26 @@ import { ErrorFetching, } from "lib/components/state"; import { ModulesTable } from "lib/components/table"; -import { useFormatAddresses } from "lib/hooks/useFormatAddresses"; import { useModulesByAddress } from "lib/services/move/moduleService"; +import type { ModuleInfo, Option } from "lib/types"; export const MyPublishedModulesTable = () => { const [keyword, setKeyword] = useState(""); const { address } = useCurrentChain(); const { - data: modulesData, + data, isFetching: isModulesLoading, error, } = useModulesByAddress(address); - const formatAddresses = useFormatAddresses(); - const mappedModules = modulesData?.map((module) => { - return { - address: formatAddresses(module.address).address, - name: module.moduleName, - functions: { - view: module.viewFunctions.length, - execute: module.executeFunctions.length, - }, - }; - }); + const filteredPublishedModules: Option = useMemo(() => { + if (!keyword) return data?.items; - const filteredPublishedModules = useMemo(() => { - if (!keyword) return mappedModules; - - return mappedModules?.filter((module) => - module.name?.toLowerCase().includes(keyword.toLowerCase()) + return data?.items.filter((module) => + module.moduleName?.toLowerCase().includes(keyword.toLowerCase()) ); - }, [keyword, mappedModules]); + }, [keyword, data?.items]); const emptyState = () => { if (error) return ; diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index 74a6d7de1..985bbda42 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -8,30 +8,56 @@ import type { Addr, ExposedFunction, HexAddr, + IndexedModule, InternalModule, + ModuleData, ModuleInfo, Nullable, ResponseABI, ResponseModule, - ResponseModules, SnakeToCamelCaseNested, } from "lib/types"; -import { - UpgradePolicy, - zBechAddr, - zHexAddr, - zRemark, - zUtcDate, -} from "lib/types"; +import { UpgradePolicy, zHexAddr, zRemark, zUtcDate } from "lib/types"; +import type { Pagination } from "lib/types/rest"; import { libDecode, parseJsonABI, - parseTxHashOpt, + parseTxHash, parseWithError, serializeAbiData, snakeToCamel, + splitViewExecuteFunctions, } from "lib/utils"; +const indexModuleAbi = (module: InternalModule): IndexedModule => { + const parsedAbi = parseJsonABI(module.abi); + const { view, execute } = splitViewExecuteFunctions( + parsedAbi.exposed_functions + ); + return { + ...module, + address: module.address as HexAddr, + parsedAbi, + viewFunctions: view, + executeFunctions: execute, + }; +}; + +interface ModuleReturn { + module: ResponseModule; +} + +export const getModuleByAddressLcd = async ( + baseEndpoint: string, + address: Addr, + moduleName: string +): Promise => { + const { data } = await axios.get( + `${baseEndpoint}/initia/move/v1/accounts/${address}/modules/${moduleName}` + ); + return indexModuleAbi(snakeToCamel(data.module)); +}; + const zAccountModulesResponseItem = z .object({ abi: z.string(), @@ -40,7 +66,7 @@ const zAccountModulesResponseItem = z raw_bytes: z.string(), upgrade_policy: z.nativeEnum(UpgradePolicy), }) - .transform(snakeToCamel); + .transform((val) => indexModuleAbi(snakeToCamel(val))); const zAccountModulesResponse = z.object({ items: z.array(zAccountModulesResponseItem), @@ -56,14 +82,19 @@ export const getModulesByAddress = async ( .get(`${endpoint}/${encodeURIComponent(address)}/move/modules`) .then(({ data }) => parseWithError(zAccountModulesResponse, data)); -export const getAccountModules = async ( +interface ModulesReturn { + modules: ResponseModule[]; + pagination: Pagination; +} + +export const getModulesByAddressLcd = async ( baseEndpoint: string, address: Addr -): Promise => { +): Promise => { const result: ResponseModule[] = []; const fetchFn = async (paginationKey: Nullable) => { - const { data } = await axios.get( + const { data } = await axios.get( `${baseEndpoint}/initia/move/v1/accounts/${address}/modules${ paginationKey ? `?pagination.key=${paginationKey}` : "" }` @@ -74,22 +105,9 @@ export const getAccountModules = async ( await fetchFn(null); - return snakeToCamel(result); -}; - -interface ModuleReturn { - module: ResponseModule; -} - -export const getAccountModule = async ( - baseEndpoint: string, - address: Addr, - moduleName: string -): Promise => { - const { data } = await axios.get( - `${baseEndpoint}/initia/move/v1/accounts/${address}/modules/${moduleName}` - ); - return snakeToCamel(data.module); + return snakeToCamel(result) + .sort((a, b) => a.moduleName.localeCompare(b.moduleName)) + .map((module) => indexModuleAbi(module)); }; interface ModuleVerificationReturn { @@ -165,21 +183,14 @@ export const decodeScript = async ( const zModulesResponseItem = z .object({ - address: zBechAddr, - name: z.string(), + address: zHexAddr, + module_name: z.string(), height: z.number(), latest_updated: zUtcDate, is_republished: z.boolean(), is_verified: z.boolean(), }) - .transform((val) => ({ - address: val.address, - name: val.name, - height: val.height, - latestUpdated: val.latest_updated, - isRepublished: val.is_republished, - isVerified: val.is_verified, - })); + .transform(snakeToCamel); const zModulesResponse = z.object({ items: z.array(zModulesResponseItem), @@ -201,7 +212,7 @@ export const getModules = async ( }) .then(({ data }) => parseWithError(zModulesResponse, data)); -const zModuleInfoResponse = z +const zModuleDataResponse = z .object({ abi: z.string(), address: zHexAddr, @@ -212,28 +223,41 @@ const zModuleInfoResponse = z recent_publish_proposal: zProposal .pick({ id: true, title: true }) .nullable(), - is_republished: z.boolean(), recent_publish_block_height: z.number().nonnegative(), recent_publish_block_timestamp: zUtcDate, + is_republished: z.boolean(), }) - .transform((val) => ({ - ...snakeToCamel(val), - recentPublishTransaction: parseTxHashOpt( - val.recent_publish_transaction ?? undefined - ), - })); -export type ModuleInfoResponse = z.infer; - -export const getModuleInfo = async ( + .transform( + ({ + recent_publish_transaction, + recent_publish_proposal, + recent_publish_block_height, + recent_publish_block_timestamp, + is_republished, + ...internalModule + }) => ({ + ...indexModuleAbi(snakeToCamel(internalModule)), + recentPublishTransaction: recent_publish_transaction + ? parseTxHash(recent_publish_transaction) + : null, + recentPublishProposal: recent_publish_proposal, + recentPublishBlockHeight: recent_publish_block_height, + recentPublishBlockTimestamp: recent_publish_block_timestamp, + isRepublished: is_republished, + }) + ); +export type ModuleDataResponse = z.infer; + +export const getModuleData = async ( endpoint: string, vmAddress: HexAddr, moduleName: string -): Promise => +): Promise => axios .get( `${endpoint}/${encodeURIComponent(vmAddress)}/${encodeURIComponent(moduleName)}/info` ) - .then(({ data }) => parseWithError(zModuleInfoResponse, data)); + .then(({ data }) => parseWithError(zModuleDataResponse, data)); const zModuleTableCountsResponse = z.object({ txs: z.number().nonnegative().nullable(), diff --git a/src/lib/services/move/moduleService.ts b/src/lib/services/move/moduleService.ts index eaea06de3..fd07d3f37 100644 --- a/src/lib/services/move/moduleService.ts +++ b/src/lib/services/move/moduleService.ts @@ -17,18 +17,18 @@ import type { Addr, ExposedFunction, HexAddr, - InternalModule, + IndexedModule, Nullable, Option, ResponseABI, RpcQueryError, UpgradePolicy, } from "lib/types"; -import { parseJsonABI, splitViewExecuteFunctions, truncate } from "lib/utils"; +import { truncate } from "lib/utils"; import type { + ModuleDataResponse, ModuleHistoriesResponse, - ModuleInfoResponse, ModuleRelatedProposalsResponse, ModulesResponse, ModuleTableCountsResponse, @@ -38,78 +38,52 @@ import type { import { decodeModule, decodeScript, - getAccountModule, - getAccountModules, getFunctionView, + getModuleByAddressLcd, + getModuleData, getModuleHistories, - getModuleInfo, getModuleRelatedProposals, getModules, getModulesByAddress, + getModulesByAddressLcd, getModuleTableCounts, getModuleTxs, getModuleVerificationStatus, } from "./module"; -export interface IndexedModule extends InternalModule { - address: HexAddr; - parsedAbi: ResponseABI; - viewFunctions: ExposedFunction[]; - executeFunctions: ExposedFunction[]; - searchedFn: Option; -} +export const useModuleByAddressLcd = ({ + address, + moduleName, + options = {}, +}: { + address: Addr; + moduleName: string; + options?: Omit, "queryKey">; +}): UseQueryResult => { + const baseEndpoint = useBaseApiRoute("rest"); + const queryFn = () => + getModuleByAddressLcd(baseEndpoint, address, moduleName); -export const indexModuleResponse = ( - module: InternalModule, - functionName?: string -): IndexedModule => { - const parsedAbi = parseJsonABI(module.abi); - const { view, execute } = splitViewExecuteFunctions( - parsedAbi.exposed_functions + return useQuery( + [CELATONE_QUERY_KEYS.ACCOUNT_MODULE, baseEndpoint, address, moduleName], + queryFn, + options ); - return { - ...module, - address: module.address as HexAddr, - parsedAbi, - viewFunctions: view, - executeFunctions: execute, - searchedFn: parsedAbi.exposed_functions.find( - (fn) => fn.name === functionName - ), - }; }; -export const useAccountModules = ({ +export const useModulesByAddressLcd = ({ address, - moduleName, - functionName, + options = {}, }: { address: Addr; - moduleName: Option; - functionName?: Option; - options?: Omit, "queryKey">; -}): UseQueryResult => { + options?: Omit, "queryKey">; +}) => { const baseEndpoint = useBaseApiRoute("rest"); - const queryFn: QueryFunction = () => - moduleName - ? getAccountModule(baseEndpoint, address, moduleName).then((module) => - indexModuleResponse(module, functionName) - ) - : getAccountModules(baseEndpoint, address).then((modules) => - modules - .sort((a, b) => a.moduleName.localeCompare(b.moduleName)) - .map((module) => indexModuleResponse(module)) - ); + const queryFn = () => getModulesByAddressLcd(baseEndpoint, address); - return useQuery( - [ - CELATONE_QUERY_KEYS.ACCOUNT_MODULES, - baseEndpoint, - address, - moduleName, - functionName, - ], + return useQuery( + [CELATONE_QUERY_KEYS.ACCOUNT_MODULES, baseEndpoint, address], queryFn, options ); @@ -123,9 +97,7 @@ export const useModulesByAddress = (address: Option) => { [CELATONE_QUERY_KEYS.MODULES_BY_ADDRESS, endpoint, address], async () => { if (!address) throw new Error("address is undefined"); - return getModulesByAddress(endpoint, address).then((modules) => - modules.items.map((module) => indexModuleResponse(module)) - ); + return getModulesByAddress(endpoint, address); }, { enabled, @@ -218,7 +190,7 @@ export const useDecodeModule = ({ const abi = await decodeModule(move.decodeApi, base64EncodedFile); const modulePath = `${truncate(abi.address)}::${abi.name}`; - const currentPolicy = await getAccountModule( + const currentPolicy = await getModuleByAddressLcd( baseEndpoint, abi.address as HexAddr, abi.name @@ -293,12 +265,12 @@ export const useModules = ( ); }; -export const useModuleInfo = (vmAddress: HexAddr, moduleName: string) => { +export const useModuleData = (vmAddress: HexAddr, moduleName: string) => { const endpoint = useBaseApiRoute("modules"); - return useQuery( - [CELATONE_QUERY_KEYS.MODULE_INFO, endpoint, vmAddress, moduleName], - async () => getModuleInfo(endpoint, vmAddress, moduleName), + return useQuery( + [CELATONE_QUERY_KEYS.MODULE_DATA, endpoint, vmAddress, moduleName], + async () => getModuleData(endpoint, vmAddress, moduleName), { retry: 1, refetchOnWindowFocus: false, @@ -307,8 +279,8 @@ export const useModuleInfo = (vmAddress: HexAddr, moduleName: string) => { }; export const useModuleTableCounts = ( - moduleName: string, - vmAddress: HexAddr + vmAddress: HexAddr, + moduleName: string ) => { const endpoint = useBaseApiRoute("modules"); diff --git a/src/lib/services/searchService.ts b/src/lib/services/searchService.ts index 3d95d047c..41a594ef5 100644 --- a/src/lib/services/searchService.ts +++ b/src/lib/services/searchService.ts @@ -22,7 +22,7 @@ import { import { useBlockData } from "./blockService"; import { useCodeDataByCodeId } from "./codeService"; import { queryContract } from "./contract"; -import { useAccountModules } from "./move/moduleService"; +import { useModuleByAddressLcd } from "./move/moduleService"; import { useAddressByICNSName, useICNSNamesByAddress } from "./nameService"; import type { ICNSNamesResponse } from "./ns"; import { usePoolByPoolId } from "./poolService"; @@ -167,16 +167,16 @@ export const useSearchHandler = ( [addr, functionName, isMove, isSomeValidAddress, moduleName] ); - const { data: moduleData, isFetching: moduleFetching } = useAccountModules({ - address: addr, - moduleName, - functionName: undefined, - options: { - enabled: enableModuleFetching, - refetchOnWindowFocus: false, - retry: false, - }, - }); + const { data: moduleData, isFetching: moduleFetching } = + useModuleByAddressLcd({ + address: addr, + moduleName: moduleName ?? "", + options: { + enabled: enableModuleFetching, + refetchOnWindowFocus: false, + retry: false, + }, + }); // TODO: handle module function later diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 7744c438e..93be2f834 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -1,6 +1,5 @@ import type { Nullable } from "../common"; import type { SnakeToCamelCaseNested } from "../converter"; -import type { Pagination } from "../rest"; export enum UpgradePolicy { ARBITRARY = "ARBITRARY", @@ -37,11 +36,6 @@ export interface ResponseModule { upgrade_policy: UpgradePolicy; } -export interface ResponseModules { - modules: ResponseModule[]; - pagination: Pagination; -} - // TODO: change address type to HexAddr after figuring out how to correctly infer NominalType intersection export interface ResponseABI { address: string; diff --git a/src/lib/types/move/module.ts b/src/lib/types/move/module.ts index ab21a4184..a8f1d76d4 100644 --- a/src/lib/types/move/module.ts +++ b/src/lib/types/move/module.ts @@ -1,15 +1,30 @@ -import type { BechAddr } from "lib/types"; +import type { HexAddr } from "../addrs"; +import type { Nullable } from "../common"; +import type { Proposal } from "../proposal"; -export interface ModuleInfo { +import type { ExposedFunction, InternalModule, ResponseABI } from "./abi"; + +export interface IndexedModule extends InternalModule { // NOTE: can also be an ica or a contract - address: BechAddr; - name: string; - functions?: { - view: number; - execute: number; - }; + address: HexAddr; + parsedAbi: ResponseABI; + viewFunctions: ExposedFunction[]; + executeFunctions: ExposedFunction[]; +} + +export interface ModuleInfo + extends Pick, + Partial> { height?: number; latestUpdated?: Date; isRepublished?: boolean; isVerified?: boolean; } + +export interface ModuleData extends IndexedModule { + recentPublishTransaction: Nullable; + recentPublishProposal: Nullable>; + recentPublishBlockHeight: number; + recentPublishBlockTimestamp: Date; + isRepublished: boolean; +} From 88d2b6e83bc364eb2c710bf86e6c9f95b346b1c6 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 1 May 2024 14:59:43 +0700 Subject: [PATCH 02/10] fix: remove unnecessary interface --- src/lib/services/move/module.ts | 3 +-- src/lib/services/move/moduleService.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index 985bbda42..46b91551c 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -246,13 +246,12 @@ const zModuleDataResponse = z isRepublished: is_republished, }) ); -export type ModuleDataResponse = z.infer; export const getModuleData = async ( endpoint: string, vmAddress: HexAddr, moduleName: string -): Promise => +): Promise => axios .get( `${endpoint}/${encodeURIComponent(vmAddress)}/${encodeURIComponent(moduleName)}/info` diff --git a/src/lib/services/move/moduleService.ts b/src/lib/services/move/moduleService.ts index fd07d3f37..18c62f084 100644 --- a/src/lib/services/move/moduleService.ts +++ b/src/lib/services/move/moduleService.ts @@ -18,6 +18,7 @@ import type { ExposedFunction, HexAddr, IndexedModule, + ModuleData, Nullable, Option, ResponseABI, @@ -27,7 +28,6 @@ import type { import { truncate } from "lib/utils"; import type { - ModuleDataResponse, ModuleHistoriesResponse, ModuleRelatedProposalsResponse, ModulesResponse, @@ -268,7 +268,7 @@ export const useModules = ( export const useModuleData = (vmAddress: HexAddr, moduleName: string) => { const endpoint = useBaseApiRoute("modules"); - return useQuery( + return useQuery( [CELATONE_QUERY_KEYS.MODULE_DATA, endpoint, vmAddress, moduleName], async () => getModuleData(endpoint, vmAddress, moduleName), { From 6520b5a9a927e9c88ce97e1f5aa3383b9cfa8a50 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 1 May 2024 21:32:26 +0700 Subject: [PATCH 03/10] feat: refactor more --- .../drawer/selector/ModuleSelectorInput.tsx | 4 +- src/lib/pages/interact/data.ts | 2 +- src/lib/services/move/module.ts | 190 +++++++----------- src/lib/types/move/abi.ts | 13 -- src/lib/types/move/module.ts | 8 +- src/lib/utils/abi.ts | 21 +- 6 files changed, 104 insertions(+), 134 deletions(-) diff --git a/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx b/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx index 0655400c7..cf202e119 100644 --- a/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx +++ b/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx @@ -11,7 +11,7 @@ import { trackUseModuleSelectionInputFill } from "lib/amplitude"; import { useExampleAddresses } from "lib/app-provider"; import { TextInput } from "lib/components/forms"; import { useFormatAddresses } from "lib/hooks/useFormatAddresses"; -import { useAccountModules } from "lib/pages/interact/data"; +import { useSearchModules } from "lib/pages/interact/data"; import { useValidateModuleInput } from "lib/pages/interact/hooks/useValidateModuleInput"; import type { IndexedModule, Option } from "lib/types"; import { splitModule } from "lib/utils"; @@ -47,7 +47,7 @@ export const ModuleSelectorInput = ({ setMode("display"); }, [addr, formatAddresses, setMode, setSelectedAddress]); - const { refetch, isFetching } = useAccountModules({ + const { refetch, isFetching } = useSearchModules({ address: addr, moduleName, onModuleSuccess: (data) => { diff --git a/src/lib/pages/interact/data.ts b/src/lib/pages/interact/data.ts index e78e15958..5dc16b373 100644 --- a/src/lib/pages/interact/data.ts +++ b/src/lib/pages/interact/data.ts @@ -6,7 +6,7 @@ import { } from "lib/services/move"; import type { Addr, IndexedModule, Option } from "lib/types"; -export const useAccountModules = ({ +export const useSearchModules = ({ address, moduleName, onModuleSuccess, diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index 46b91551c..b4c914063 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -9,126 +9,108 @@ import type { ExposedFunction, HexAddr, IndexedModule, - InternalModule, ModuleData, ModuleInfo, Nullable, ResponseABI, - ResponseModule, - SnakeToCamelCaseNested, } from "lib/types"; import { UpgradePolicy, zHexAddr, zRemark, zUtcDate } from "lib/types"; -import type { Pagination } from "lib/types/rest"; +import { zPagination } from "lib/types/rest"; import { + indexModuleAbi, libDecode, parseJsonABI, parseTxHash, parseWithError, serializeAbiData, snakeToCamel, - splitViewExecuteFunctions, } from "lib/utils"; -const indexModuleAbi = (module: InternalModule): IndexedModule => { - const parsedAbi = parseJsonABI(module.abi); - const { view, execute } = splitViewExecuteFunctions( - parsedAbi.exposed_functions - ); - return { - ...module, - address: module.address as HexAddr, - parsedAbi, - viewFunctions: view, - executeFunctions: execute, - }; -}; +const zBaseModuleLcd = z.object({ + address: zHexAddr, + module_name: z.string(), + abi: z.string(), + raw_bytes: z.string(), + upgrade_policy: z.nativeEnum(UpgradePolicy), +}); -interface ModuleReturn { - module: ResponseModule; -} +const zIndexedModuleLcd = zBaseModuleLcd.transform((val) => ({ + ...snakeToCamel(val), + ...indexModuleAbi(val.abi), +})); + +const zModuleLcdReturn = z.object({ + module: zIndexedModuleLcd, +}); export const getModuleByAddressLcd = async ( baseEndpoint: string, address: Addr, moduleName: string -): Promise => { - const { data } = await axios.get( - `${baseEndpoint}/initia/move/v1/accounts/${address}/modules/${moduleName}` - ); - return indexModuleAbi(snakeToCamel(data.module)); -}; - -const zAccountModulesResponseItem = z - .object({ - abi: z.string(), - address: zHexAddr, - module_name: z.string(), - raw_bytes: z.string(), - upgrade_policy: z.nativeEnum(UpgradePolicy), - }) - .transform((val) => indexModuleAbi(snakeToCamel(val))); - -const zAccountModulesResponse = z.object({ - items: z.array(zAccountModulesResponseItem), - total: z.number().nonnegative(), -}); -type AccountModulesResponse = z.infer; - -export const getModulesByAddress = async ( - endpoint: string, - address: Addr -): Promise => +): Promise => axios - .get(`${endpoint}/${encodeURIComponent(address)}/move/modules`) - .then(({ data }) => parseWithError(zAccountModulesResponse, data)); + .get( + `${baseEndpoint}/initia/move/v1/accounts/${address}/modules/${moduleName}` + ) + .then(({ data }) => parseWithError(zModuleLcdReturn, data).module); -interface ModulesReturn { - modules: ResponseModule[]; - pagination: Pagination; -} +const zModulesLcdReturn = z.object({ + modules: z.array(zIndexedModuleLcd), + pagination: zPagination, +}); export const getModulesByAddressLcd = async ( baseEndpoint: string, address: Addr ): Promise => { - const result: ResponseModule[] = []; + const result: IndexedModule[] = []; const fetchFn = async (paginationKey: Nullable) => { - const { data } = await axios.get( - `${baseEndpoint}/initia/move/v1/accounts/${address}/modules${ - paginationKey ? `?pagination.key=${paginationKey}` : "" - }` - ); - result.push(...data.modules); - if (data.pagination.next_key) await fetchFn(data.pagination.next_key); + const res = await axios + .get( + `${baseEndpoint}/initia/move/v1/accounts/${address}/modules${ + paginationKey ? `?pagination.key=${paginationKey}` : "" + }` + ) + .then(({ data }) => parseWithError(zModulesLcdReturn, data)); + result.push(...res.modules); + if (res.pagination.next_key) await fetchFn(res.pagination.next_key); }; await fetchFn(null); - return snakeToCamel(result) - .sort((a, b) => a.moduleName.localeCompare(b.moduleName)) - .map((module) => indexModuleAbi(module)); + return result.sort((a, b) => a.moduleName.localeCompare(b.moduleName)); }; -interface ModuleVerificationReturn { - id: number; - module_address: HexAddr; - module_name: string; - verified_at: string; - digest: string; - source: string; - base64: string; - chain_id: string; -} +const zAccountModulesResponse = z.object({ + items: z.array(zIndexedModuleLcd), + total: z.number().nonnegative(), +}); +type AccountModulesResponse = z.infer; -// TODO: Figure out how to correctly infer NominalType intersection -export interface ModuleVerificationInternal - extends Omit< - SnakeToCamelCaseNested, - "moduleAddress" - > { - moduleAddress: HexAddr; -} +export const getModulesByAddress = async ( + endpoint: string, + address: Addr +): Promise => + axios + .get(`${endpoint}/${encodeURIComponent(address)}/move/modules`) + .then(({ data }) => parseWithError(zAccountModulesResponse, data)); + +const zModuleVerificationInternal = z + .object({ + id: z.number(), + module_address: zHexAddr, + module_name: z.string(), + verified_at: z.string(), + digest: z.string(), + source: z.string(), + base64: z.string(), + chain_id: z.string(), + }) + .transform(snakeToCamel); +export type ModuleVerificationInternal = z.infer< + typeof zModuleVerificationInternal +>; export const getModuleVerificationStatus = async ( endpoint: string, @@ -136,11 +118,8 @@ export const getModuleVerificationStatus = async ( moduleName: string ): Promise> => axios - .get(`${endpoint}/${address}/${moduleName}`) - .then(({ data }) => ({ - ...snakeToCamel(data), - moduleAddress: data.module_address, - })) + .get(`${endpoint}/${address}/${moduleName}`) + .then(({ data }) => parseWithError(zModuleVerificationInternal, data)) .catch(() => null); export const getFunctionView = async ( @@ -212,13 +191,8 @@ export const getModules = async ( }) .then(({ data }) => parseWithError(zModulesResponse, data)); -const zModuleDataResponse = z - .object({ - abi: z.string(), - address: zHexAddr, - module_name: z.string(), - raw_bytes: z.string(), - upgrade_policy: z.nativeEnum(UpgradePolicy), +const zModuleDataResponse = zBaseModuleLcd + .extend({ recent_publish_transaction: z.string().nullable(), recent_publish_proposal: zProposal .pick({ id: true, title: true }) @@ -227,25 +201,13 @@ const zModuleDataResponse = z recent_publish_block_timestamp: zUtcDate, is_republished: z.boolean(), }) - .transform( - ({ - recent_publish_transaction, - recent_publish_proposal, - recent_publish_block_height, - recent_publish_block_timestamp, - is_republished, - ...internalModule - }) => ({ - ...indexModuleAbi(snakeToCamel(internalModule)), - recentPublishTransaction: recent_publish_transaction - ? parseTxHash(recent_publish_transaction) - : null, - recentPublishProposal: recent_publish_proposal, - recentPublishBlockHeight: recent_publish_block_height, - recentPublishBlockTimestamp: recent_publish_block_timestamp, - isRepublished: is_republished, - }) - ); + .transform((val) => ({ + ...snakeToCamel(val), + ...indexModuleAbi(val.abi), + recentPublishTransaction: val.recent_publish_transaction + ? parseTxHash(val.recent_publish_transaction) + : null, + })); export const getModuleData = async ( endpoint: string, diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 93be2f834..45e4484e4 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -1,5 +1,4 @@ import type { Nullable } from "../common"; -import type { SnakeToCamelCaseNested } from "../converter"; export enum UpgradePolicy { ARBITRARY = "ARBITRARY", @@ -26,16 +25,6 @@ interface ABIFunction { argsTypes: string[]; } -/* response */ -// TODO: change address type to HexAddr after figuring out how to correctly infer NominalType intersection -export interface ResponseModule { - address: string; - module_name: string; - abi: string; - raw_bytes: string; - upgrade_policy: UpgradePolicy; -} - // TODO: change address type to HexAddr after figuring out how to correctly infer NominalType intersection export interface ResponseABI { address: string; @@ -45,8 +34,6 @@ export interface ResponseABI { structs: Struct[]; } -export type InternalModule = SnakeToCamelCaseNested; - export interface ExposedFunction { name: string; visibility: Visibility; diff --git a/src/lib/types/move/module.ts b/src/lib/types/move/module.ts index a8f1d76d4..022edb56c 100644 --- a/src/lib/types/move/module.ts +++ b/src/lib/types/move/module.ts @@ -2,11 +2,15 @@ import type { HexAddr } from "../addrs"; import type { Nullable } from "../common"; import type { Proposal } from "../proposal"; -import type { ExposedFunction, InternalModule, ResponseABI } from "./abi"; +import type { ExposedFunction, ResponseABI, UpgradePolicy } from "./abi"; -export interface IndexedModule extends InternalModule { +export interface IndexedModule { // NOTE: can also be an ica or a contract address: HexAddr; + moduleName: string; + abi: string; + rawBytes: string; + upgradePolicy: UpgradePolicy; parsedAbi: ResponseABI; viewFunctions: ExposedFunction[]; executeFunctions: ExposedFunction[]; diff --git a/src/lib/utils/abi.ts b/src/lib/utils/abi.ts index 91fa7973d..687c0fea4 100644 --- a/src/lib/utils/abi.ts +++ b/src/lib/utils/abi.ts @@ -1,6 +1,11 @@ import { BCS } from "@initia/initia.js"; -import type { AbiFormData, ExposedFunction, Nullable } from "lib/types"; +import type { + AbiFormData, + ExposedFunction, + Nullable, + ResponseABI, +} from "lib/types"; export const checkAvailability = (fn: ExposedFunction) => fn.is_view || fn.is_entry; @@ -19,7 +24,7 @@ const sortByAvailability = (a: ExposedFunction, b: ExposedFunction) => { return checkAvailability(a) ? -1 : 1; }; -export const splitViewExecuteFunctions = (functions: ExposedFunction[]) => { +const splitViewExecuteFunctions = (functions: ExposedFunction[]) => { const functionMap = functions.reduce<{ view: ExposedFunction[]; execute: ExposedFunction[]; @@ -44,6 +49,18 @@ export const splitViewExecuteFunctions = (functions: ExposedFunction[]) => { return functionMap; }; +export const indexModuleAbi = (abi: string) => { + const parsedAbi = parseJsonABI(abi); + const { view, execute } = splitViewExecuteFunctions( + parsedAbi.exposed_functions + ); + return { + parsedAbi, + viewFunctions: view, + executeFunctions: execute, + }; +}; + export const getAbiInitialData = (length: number) => Array(length) .fill("") From 0195875729fbbd8869b67525d1b6de67161a8158 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 1 May 2024 21:38:32 +0700 Subject: [PATCH 04/10] fix: security check --- src/lib/services/move/module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index b4c914063..2a3042a90 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -50,7 +50,7 @@ export const getModuleByAddressLcd = async ( ): Promise => axios .get( - `${baseEndpoint}/initia/move/v1/accounts/${address}/modules/${moduleName}` + `${baseEndpoint}/initia/move/v1/accounts/${encodeURIComponent(address)}/modules/${encodeURIComponent(moduleName)}` ) .then(({ data }) => parseWithError(zModuleLcdReturn, data).module); From 878d7007ac1e84330eaedfb8e3ca8a1766cea5e7 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 1 May 2024 21:57:10 +0700 Subject: [PATCH 05/10] fix: disable input while fetching --- .../interact/component/drawer/selector/ModuleSelectorInput.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx b/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx index cf202e119..a3041982d 100644 --- a/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx +++ b/src/lib/pages/interact/component/drawer/selector/ModuleSelectorInput.tsx @@ -112,6 +112,7 @@ export const ModuleSelectorInput = ({ Date: Thu, 2 May 2024 09:35:57 +0700 Subject: [PATCH 06/10] fix: move upgrade poligy to module type --- src/lib/types/move/abi.ts | 37 +++++++++++++++--------------------- src/lib/types/move/module.ts | 8 +++++++- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 45e4484e4..1b80c9b7c 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -1,29 +1,22 @@ import type { Nullable } from "../common"; -export enum UpgradePolicy { - ARBITRARY = "ARBITRARY", - COMPATIBLE = "COMPATIBLE", - IMMUTABLE = "IMMUTABLE", -} - export type Visibility = "public" | "friend" | "private" | "script"; -// TODO: revisit address type later -export interface ABIModule { - address: string; - name: string; - functions: ABIFunction[]; -} - -// TODO: revisit moduleAddress type later -interface ABIFunction { - method: "query" | "tx"; - moduleAddress: string; - moduleName: string; - functionName: string; - typeArgsLength: number; - argsTypes: string[]; -} +// NOTE: not used, but keeping it just in case for now +// export interface ABIModule { +// address: string; // revisit type +// name: string; +// functions: ABIFunction[]; +// } +// +// interface ABIFunction { +// method: "query" | "tx"; +// moduleAddress: string; // revisit type +// moduleName: string; +// functionName: string; +// typeArgsLength: number; +// argsTypes: string[]; +// } // TODO: change address type to HexAddr after figuring out how to correctly infer NominalType intersection export interface ResponseABI { diff --git a/src/lib/types/move/module.ts b/src/lib/types/move/module.ts index 022edb56c..d9e995720 100644 --- a/src/lib/types/move/module.ts +++ b/src/lib/types/move/module.ts @@ -2,7 +2,13 @@ import type { HexAddr } from "../addrs"; import type { Nullable } from "../common"; import type { Proposal } from "../proposal"; -import type { ExposedFunction, ResponseABI, UpgradePolicy } from "./abi"; +import type { ExposedFunction, ResponseABI } from "./abi"; + +export enum UpgradePolicy { + ARBITRARY = "ARBITRARY", + COMPATIBLE = "COMPATIBLE", + IMMUTABLE = "IMMUTABLE", +} export interface IndexedModule { // NOTE: can also be an ica or a contract From a10685900286b8f9710706400d48e89c69b5c78a Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 2 May 2024 09:39:09 +0700 Subject: [PATCH 07/10] fix: addr type --- src/lib/types/move/abi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 1b80c9b7c..5be6da6b6 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -1,3 +1,4 @@ +import type { HexAddr } from "../addrs"; import type { Nullable } from "../common"; export type Visibility = "public" | "friend" | "private" | "script"; @@ -18,9 +19,8 @@ export type Visibility = "public" | "friend" | "private" | "script"; // argsTypes: string[]; // } -// TODO: change address type to HexAddr after figuring out how to correctly infer NominalType intersection export interface ResponseABI { - address: string; + address: HexAddr; name: string; friends: string[]; exposed_functions: ExposedFunction[]; From 0c4ccfb767b56f867243d1cf4a3c17f31d03bb60 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 2 May 2024 09:42:04 +0700 Subject: [PATCH 08/10] fix: renaming name for convention --- src/lib/services/move/module.ts | 6 +++--- src/lib/services/move/moduleService.ts | 4 ++-- src/lib/types/move/abi.ts | 8 ++++---- src/lib/types/move/module.ts | 4 ++-- src/lib/utils/abi.ts | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index 2a3042a90..ea8246bb6 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -12,7 +12,7 @@ import type { ModuleData, ModuleInfo, Nullable, - ResponseABI, + ResponseAbi, } from "lib/types"; import { UpgradePolicy, zHexAddr, zRemark, zUtcDate } from "lib/types"; import { zPagination } from "lib/types/rest"; @@ -143,12 +143,12 @@ interface DecodeModuleReturn { export const decodeModule = async ( decodeAPI: string, moduleEncode: string -): Promise => +): Promise => axios .post(decodeAPI, { code_bytes: moduleEncode, }) - .then(({ data }) => parseJsonABI(libDecode(data.abi))); + .then(({ data }) => parseJsonABI(libDecode(data.abi))); export const decodeScript = async ( decodeAPI: string, diff --git a/src/lib/services/move/moduleService.ts b/src/lib/services/move/moduleService.ts index 18c62f084..3a852be6d 100644 --- a/src/lib/services/move/moduleService.ts +++ b/src/lib/services/move/moduleService.ts @@ -21,7 +21,7 @@ import type { ModuleData, Nullable, Option, - ResponseABI, + ResponseAbi, RpcQueryError, UpgradePolicy, } from "lib/types"; @@ -170,7 +170,7 @@ export const useFunctionView = ({ ); }; export interface DecodeModuleQueryResponse { - abi: ResponseABI; + abi: ResponseAbi; modulePath: string; currentPolicy: Option; } diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 5be6da6b6..81f11a284 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -4,13 +4,13 @@ import type { Nullable } from "../common"; export type Visibility = "public" | "friend" | "private" | "script"; // NOTE: not used, but keeping it just in case for now -// export interface ABIModule { +// export interface AbiModule { // address: string; // revisit type // name: string; -// functions: ABIFunction[]; +// functions: AbiFunction[]; // } // -// interface ABIFunction { +// interface AbiFunction { // method: "query" | "tx"; // moduleAddress: string; // revisit type // moduleName: string; @@ -19,7 +19,7 @@ export type Visibility = "public" | "friend" | "private" | "script"; // argsTypes: string[]; // } -export interface ResponseABI { +export interface ResponseAbi { address: HexAddr; name: string; friends: string[]; diff --git a/src/lib/types/move/module.ts b/src/lib/types/move/module.ts index d9e995720..dc560a7e9 100644 --- a/src/lib/types/move/module.ts +++ b/src/lib/types/move/module.ts @@ -2,7 +2,7 @@ import type { HexAddr } from "../addrs"; import type { Nullable } from "../common"; import type { Proposal } from "../proposal"; -import type { ExposedFunction, ResponseABI } from "./abi"; +import type { ExposedFunction, ResponseAbi } from "./abi"; export enum UpgradePolicy { ARBITRARY = "ARBITRARY", @@ -17,7 +17,7 @@ export interface IndexedModule { abi: string; rawBytes: string; upgradePolicy: UpgradePolicy; - parsedAbi: ResponseABI; + parsedAbi: ResponseAbi; viewFunctions: ExposedFunction[]; executeFunctions: ExposedFunction[]; } diff --git a/src/lib/utils/abi.ts b/src/lib/utils/abi.ts index 687c0fea4..8ecbe2754 100644 --- a/src/lib/utils/abi.ts +++ b/src/lib/utils/abi.ts @@ -4,7 +4,7 @@ import type { AbiFormData, ExposedFunction, Nullable, - ResponseABI, + ResponseAbi, } from "lib/types"; export const checkAvailability = (fn: ExposedFunction) => @@ -50,7 +50,7 @@ const splitViewExecuteFunctions = (functions: ExposedFunction[]) => { }; export const indexModuleAbi = (abi: string) => { - const parsedAbi = parseJsonABI(abi); + const parsedAbi = parseJsonABI(abi); const { view, execute } = splitViewExecuteFunctions( parsedAbi.exposed_functions ); From 4a4adbb11895dfb688f6fd4c1c81dc4fef87a869 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 2 May 2024 11:26:51 +0700 Subject: [PATCH 09/10] fix: comment --- src/lib/services/move/module.ts | 12 +++++++----- src/lib/services/move/moduleService.ts | 4 ++-- src/lib/types/move/abi.ts | 18 +----------------- src/lib/types/move/module.ts | 4 ++-- src/lib/utils/abi.ts | 4 ++-- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index ea8246bb6..3f7b68862 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -9,10 +9,10 @@ import type { ExposedFunction, HexAddr, IndexedModule, + ModuleAbi, ModuleData, ModuleInfo, Nullable, - ResponseAbi, } from "lib/types"; import { UpgradePolicy, zHexAddr, zRemark, zUtcDate } from "lib/types"; import { zPagination } from "lib/types/rest"; @@ -68,7 +68,7 @@ export const getModulesByAddressLcd = async ( const fetchFn = async (paginationKey: Nullable) => { const res = await axios .get( - `${baseEndpoint}/initia/move/v1/accounts/${address}/modules${ + `${baseEndpoint}/initia/move/v1/accounts/${encodeURIComponent(address)}/modules${ paginationKey ? `?pagination.key=${paginationKey}` : "" }` ) @@ -118,7 +118,9 @@ export const getModuleVerificationStatus = async ( moduleName: string ): Promise> => axios - .get(`${endpoint}/${address}/${moduleName}`) + .get( + `${endpoint}/${encodeURIComponent(address)}/${encodeURIComponent(moduleName)}` + ) .then(({ data }) => parseWithError(zModuleVerificationInternal, data)) .catch(() => null); @@ -143,12 +145,12 @@ interface DecodeModuleReturn { export const decodeModule = async ( decodeAPI: string, moduleEncode: string -): Promise => +): Promise => axios .post(decodeAPI, { code_bytes: moduleEncode, }) - .then(({ data }) => parseJsonABI(libDecode(data.abi))); + .then(({ data }) => parseJsonABI(libDecode(data.abi))); export const decodeScript = async ( decodeAPI: string, diff --git a/src/lib/services/move/moduleService.ts b/src/lib/services/move/moduleService.ts index 3a852be6d..1c5c4fe7b 100644 --- a/src/lib/services/move/moduleService.ts +++ b/src/lib/services/move/moduleService.ts @@ -18,10 +18,10 @@ import type { ExposedFunction, HexAddr, IndexedModule, + ModuleAbi, ModuleData, Nullable, Option, - ResponseAbi, RpcQueryError, UpgradePolicy, } from "lib/types"; @@ -170,7 +170,7 @@ export const useFunctionView = ({ ); }; export interface DecodeModuleQueryResponse { - abi: ResponseAbi; + abi: ModuleAbi; modulePath: string; currentPolicy: Option; } diff --git a/src/lib/types/move/abi.ts b/src/lib/types/move/abi.ts index 81f11a284..97fe279df 100644 --- a/src/lib/types/move/abi.ts +++ b/src/lib/types/move/abi.ts @@ -3,23 +3,7 @@ import type { Nullable } from "../common"; export type Visibility = "public" | "friend" | "private" | "script"; -// NOTE: not used, but keeping it just in case for now -// export interface AbiModule { -// address: string; // revisit type -// name: string; -// functions: AbiFunction[]; -// } -// -// interface AbiFunction { -// method: "query" | "tx"; -// moduleAddress: string; // revisit type -// moduleName: string; -// functionName: string; -// typeArgsLength: number; -// argsTypes: string[]; -// } - -export interface ResponseAbi { +export interface ModuleAbi { address: HexAddr; name: string; friends: string[]; diff --git a/src/lib/types/move/module.ts b/src/lib/types/move/module.ts index dc560a7e9..61bf320d7 100644 --- a/src/lib/types/move/module.ts +++ b/src/lib/types/move/module.ts @@ -2,7 +2,7 @@ import type { HexAddr } from "../addrs"; import type { Nullable } from "../common"; import type { Proposal } from "../proposal"; -import type { ExposedFunction, ResponseAbi } from "./abi"; +import type { ExposedFunction, ModuleAbi } from "./abi"; export enum UpgradePolicy { ARBITRARY = "ARBITRARY", @@ -17,7 +17,7 @@ export interface IndexedModule { abi: string; rawBytes: string; upgradePolicy: UpgradePolicy; - parsedAbi: ResponseAbi; + parsedAbi: ModuleAbi; viewFunctions: ExposedFunction[]; executeFunctions: ExposedFunction[]; } diff --git a/src/lib/utils/abi.ts b/src/lib/utils/abi.ts index 8ecbe2754..0d08fd928 100644 --- a/src/lib/utils/abi.ts +++ b/src/lib/utils/abi.ts @@ -3,8 +3,8 @@ import { BCS } from "@initia/initia.js"; import type { AbiFormData, ExposedFunction, + ModuleAbi, Nullable, - ResponseAbi, } from "lib/types"; export const checkAvailability = (fn: ExposedFunction) => @@ -50,7 +50,7 @@ const splitViewExecuteFunctions = (functions: ExposedFunction[]) => { }; export const indexModuleAbi = (abi: string) => { - const parsedAbi = parseJsonABI(abi); + const parsedAbi = parseJsonABI(abi); const { view, execute } = splitViewExecuteFunctions( parsedAbi.exposed_functions ); From 00b0c97f8315c1c95cff5854537ed7d8e051437c Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Thu, 2 May 2024 11:30:12 +0700 Subject: [PATCH 10/10] fix: modules creator --- .../table/modules/ModulesTableMobileCard.tsx | 11 +++++------ src/lib/components/table/modules/ModulesTableRow.tsx | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/lib/components/table/modules/ModulesTableMobileCard.tsx b/src/lib/components/table/modules/ModulesTableMobileCard.tsx index b3ac76967..686298f72 100644 --- a/src/lib/components/table/modules/ModulesTableMobileCard.tsx +++ b/src/lib/components/table/modules/ModulesTableMobileCard.tsx @@ -4,6 +4,7 @@ import { MobileCardTemplate } from "../MobileCardTemplate"; import { MobileLabel } from "../MobileLabel"; import { useInternalNavigate } from "lib/app-provider"; import { ExplorerLink } from "lib/components/ExplorerLink"; +import { useFormatAddresses } from "lib/hooks/useFormatAddresses"; import type { ModuleInfo } from "lib/types"; import { dateFromNow, formatUTC } from "lib/utils"; @@ -17,6 +18,8 @@ export const ModulesTableMobileCard = ({ moduleInfo, }: ModulesTableMobileCardProps) => { const navigate = useInternalNavigate(); + const formatAddresses = useFormatAddresses(); + const { address: creator } = formatAddresses(moduleInfo.address); return ( - - + + {moduleInfo.latestUpdated && ( diff --git a/src/lib/components/table/modules/ModulesTableRow.tsx b/src/lib/components/table/modules/ModulesTableRow.tsx index b1e7da4a0..a64079ad2 100644 --- a/src/lib/components/table/modules/ModulesTableRow.tsx +++ b/src/lib/components/table/modules/ModulesTableRow.tsx @@ -24,7 +24,7 @@ export const ModulesTableRow = ({ }: ModulesTableRowProps) => { const navigate = useInternalNavigate(); const formatAddresses = useFormatAddresses(); - const { address } = formatAddresses(moduleInfo.address); + const { address: creator } = formatAddresses(moduleInfo.address); return ( @@ -70,7 +70,7 @@ export const ModulesTableRow = ({ )} - + {!isPublishedModules && moduleInfo.latestUpdated && (