From 795100b42dba2bdfb320d0aefafc347de60b1b40 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Sun, 24 Dec 2023 00:43:57 +0700 Subject: [PATCH 1/6] feat: api v1 - contract migration table --- CHANGELOG.md | 1 + src/lib/app-provider/env.ts | 2 +- .../tables/RelatedProposalsTable.tsx | 10 +-- src/lib/query/proposal.ts | 29 -------- src/lib/services/proposal.ts | 74 ++++++++++++++++--- src/lib/services/proposalService.ts | 55 +++++--------- 6 files changed, 87 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f519353e2..b1dbfbc01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +- [#697](https://github.com/alleslabs/celatone-frontend/pull/697) api v1 - contract tables (migrations and related proposals) - [#696](https://github.com/alleslabs/celatone-frontend/pull/696) api v1 - block details - [#667](https://github.com/alleslabs/celatone-frontend/pull/667) Adjust for search bar consistency - [#692](https://github.com/alleslabs/celatone-frontend/pull/692) Add verify link for mahalo diff --git a/src/lib/app-provider/env.ts b/src/lib/app-provider/env.ts index 82398825a..4de35a268 100644 --- a/src/lib/app-provider/env.ts +++ b/src/lib/app-provider/env.ts @@ -64,7 +64,7 @@ export enum CELATONE_QUERY_KEYS { // FAUCET FAUCET_INFO = "CELATONE_QUERY_FAUCET_INFO", // X/GOV - RELATED_PROPOSALS_BY_CONTRACT_ADDRESS_PAGINATION = "CELATONE_QUERY_RELATED_PROPOSALS_BY_CONTRACT_ADDRESS_PAGINATION", + RELATED_PROPOSALS_BY_CONTRACT_ADDRESS = "CELATONE_QUERY_RELATED_PROPOSALS_BY_CONTRACT_ADDRESS", RELATED_PROPOSALS_BY_CONTRACT_ADDRESS_COUNT = "CELATONE_QUERY_RELATED_PROPOSALS_BY_CONTRACT_ADDRESS_COUNT", PROPOSALS_BY_WALLET_ADDRESS_PAGINATION = "CELATONE_QUERY_PROPOSALS_BY_WALLET_ADDRESS_PAGINATION", PROPOSALS_BY_WALLET_ADDRESS_COUNT = "CELATONE_QUERY_PROPOSALS_BY_WALLET_ADDRESS_COUNT", diff --git a/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx b/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx index 38c44a3dc..2541ed62e 100644 --- a/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx +++ b/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx @@ -4,7 +4,7 @@ import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; import { EmptyState, ErrorFetching } from "lib/components/state"; import { ProposalsTable } from "lib/components/table"; -import { useRelatedProposalsByContractAddressPagination } from "lib/services/proposalService"; +import { useRelatedProposalsByContractAddress } from "lib/services/proposalService"; import type { ContractAddr, Option } from "lib/types"; interface RelatedProposalsTableProps { @@ -40,11 +40,7 @@ export const RelatedProposalsTable = ({ data: relatedProposals, isLoading, error, - } = useRelatedProposalsByContractAddressPagination( - contractAddress, - offset, - pageSize - ); + } = useRelatedProposalsByContractAddress(contractAddress, offset, pageSize); const onPageChange = (nextPage: number) => { refetchCount(); @@ -61,7 +57,7 @@ export const RelatedProposalsTable = ({ return ( <> ; +export type ProposalsResponse = z.infer; export const getProposalsByAddress = async ( endpoint: string, address: Addr, limit: number, offset: number -): Promise => +): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/proposals`, { params: { @@ -108,4 +108,54 @@ export const getProposalsByAddress = async ( offset, }, }) - .then((res) => zProposalResponse.parse(res.data)); + .then((res) => zProposalsResponse.parse(res.data)); + +const zRelatedProposalsResponseItem = z + .object({ + deposit_end_time: zUtcDate, + proposal_id: z.number().nonnegative(), + is_expedited: z.boolean(), + proposer: zAddr, + resolved_height: z.number().nullish(), + status: z.string().transform(parseProposalStatus), + title: z.string(), + type: z.string(), + voting_end_time: zUtcDate, + }) + .transform((val) => ({ + depositEndTime: val.deposit_end_time, + proposalId: val.proposal_id, + isExpedited: val.is_expedited, + proposer: val.proposer, + resolvedHeight: val.resolved_height, + status: val.status, + title: val.title, + type: val.type as ProposalType, // TODO: remove type assertion + votingEndTime: val.voting_end_time, + })); + +const zRelatedProposalsResponse = z.object({ + items: z.array(zRelatedProposalsResponseItem), +}); + +export type RelatedProposalsResponse = z.infer< + typeof zRelatedProposalsResponse +>; + +export const getRelatedProposalsByContractAddress = async ( + endpoint: string, + contractAddress: ContractAddr, + limit: number, + offset: number +): Promise => + axios + .get( + `${endpoint}/${encodeURIComponent(contractAddress)}/related-proposals`, + { + params: { + limit, + offset, + }, + } + ) + .then((res) => zRelatedProposalsResponse.parse(res.data)); diff --git a/src/lib/services/proposalService.ts b/src/lib/services/proposalService.ts index ca12c0d18..3d2583bea 100644 --- a/src/lib/services/proposalService.ts +++ b/src/lib/services/proposalService.ts @@ -14,7 +14,6 @@ import { getProposalsByWalletAddressPagination, getProposalsCountByWalletAddress, getProposalTypes, - getRelatedProposalsByContractAddressPagination, getRelatedProposalsByModuleIdPagination, getRelatedProposalsCountByContractAddress, getRelatedProposalsCountByModuleId, @@ -44,7 +43,8 @@ import { useAssetInfos } from "./assetService"; import { useProposalListExpression } from "./expression"; import type { DepositParamsInternal, - ProposalResponse, + ProposalsResponse, + RelatedProposalsResponse, UploadAccess, VotingParamsInternal, } from "./proposal"; @@ -53,49 +53,34 @@ import { fetchGovDepositParams, fetchGovUploadAccessParams, getProposalsByAddress, + getRelatedProposalsByContractAddress, } from "./proposal"; -export const useRelatedProposalsByContractAddressPagination = ( +export const useRelatedProposalsByContractAddress = ( contractAddress: ContractAddr, offset: number, - pageSize: number -): UseQueryResult => { - const { indexerGraphClient } = useCelatoneApp(); - - const queryFn = useCallback(async () => { - return indexerGraphClient - .request(getRelatedProposalsByContractAddressPagination, { - contractAddress, - offset, - pageSize, - }) - .then(({ contract_proposals }) => - contract_proposals.map((proposal) => ({ - proposalId: proposal.proposal_id, - title: proposal.proposal.title, - status: parseProposalStatus(proposal.proposal.status), - votingEndTime: parseDate(proposal.proposal.voting_end_time), - depositEndTime: parseDate(proposal.proposal.deposit_end_time), - resolvedHeight: proposal.resolved_height, - type: proposal.proposal.type as ProposalType, - proposer: proposal.proposal.account?.address as Addr, - isExpedited: Boolean(proposal.proposal.is_expedited), - })) - ); - }, [contractAddress, offset, pageSize, indexerGraphClient]); + limit: number +) => { + const endpoint = useBaseApiRoute("contracts"); - return useQuery( + return useQuery( [ - CELATONE_QUERY_KEYS.RELATED_PROPOSALS_BY_CONTRACT_ADDRESS_PAGINATION, + CELATONE_QUERY_KEYS.RELATED_PROPOSALS_BY_CONTRACT_ADDRESS, + endpoint, contractAddress, + limit, offset, - pageSize, - indexerGraphClient, ], - queryFn, + async () => + getRelatedProposalsByContractAddress( + endpoint, + contractAddress, + limit, + offset + ), { + retry: 1, keepPreviousData: true, - enabled: !!contractAddress, } ); }; @@ -134,7 +119,7 @@ export const useProposalsByAddress = ( address: Addr, offset: number, limit: number -): UseQueryResult => { +): UseQueryResult => { const endpoint = useBaseApiRoute("accounts"); return useQuery( From dbc2deca74c6a4e126aa111a975e917ff42cb462 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:06:46 +0700 Subject: [PATCH 2/6] feat: api v1 - contract migration table --- src/lib/app-provider/env.ts | 2 +- src/lib/app-provider/hooks/useBaseApiRoute.ts | 2 +- .../components/tables/migration/index.tsx | 40 +++++------ src/lib/pages/contract-details/data.ts | 37 +++++----- src/lib/query/contract.ts | 32 --------- src/lib/services/account.ts | 4 +- src/lib/services/asset.ts | 2 +- src/lib/services/balance.ts | 2 +- src/lib/services/block.ts | 4 +- src/lib/services/code.ts | 2 +- src/lib/services/contract.ts | 67 +++++++++++++++---- src/lib/services/contractService.ts | 56 ++++++---------- src/lib/services/delegation.ts | 2 +- src/lib/services/move/module.ts | 4 +- src/lib/services/move/pool.ts | 2 +- src/lib/services/move/resource.ts | 2 +- src/lib/services/overview.ts | 2 +- src/lib/services/proposal.ts | 4 +- src/lib/services/tx.ts | 10 +-- src/lib/types/contract.ts | 23 ++++--- src/lib/types/tx/transaction.ts | 4 +- 21 files changed, 149 insertions(+), 154 deletions(-) diff --git a/src/lib/app-provider/env.ts b/src/lib/app-provider/env.ts index 4de35a268..acb633529 100644 --- a/src/lib/app-provider/env.ts +++ b/src/lib/app-provider/env.ts @@ -45,7 +45,7 @@ export enum CELATONE_QUERY_KEYS { INSTANTIATED_LIST_BY_WALLET_ADDRESS = "CELATONE_QUERY_INSTANTIATED_LIST_BY_WALLET_ADDRESS", ADMIN_CONTRACTS_BY_ADDRESS = "CELATONE_QUERY_ADMIN_CONTRACTS_BY_ADDRESS", ADMINS_BY_CONTRACTS = "CELATONE_QUERY_ADMINS_BY_CONTRACTS", - CONTRACT_MIGRATION_HISTORIES_PAGINATION = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_PAGINATION", + CONTRACT_MIGRATION_HISTORIES = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES", CONTRACT_MIGRATION_HISTORIES_COUNT = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_COUNT", CONTRACTS_BY_CODE_ID_PAGINATION = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_PAGINATION", CONTRACTS_BY_CODE_ID_COUNT = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_COUNT", diff --git a/src/lib/app-provider/hooks/useBaseApiRoute.ts b/src/lib/app-provider/hooks/useBaseApiRoute.ts index e52f774f3..6ada0d430 100644 --- a/src/lib/app-provider/hooks/useBaseApiRoute.ts +++ b/src/lib/app-provider/hooks/useBaseApiRoute.ts @@ -46,7 +46,7 @@ export const useBaseApiRoute = ( case "projects": return `${api}/projects/${chain}/${currentChainId}`; case "contracts": - return `${api}/contracts/${chain}/${currentChainId}`; + return `${api}/v1/${chain}/${currentChainId}/contracts`; case "codes": return `${api}/codes/${chain}/${currentChainId}`; case "legacy.accounts": diff --git a/src/lib/pages/contract-details/components/tables/migration/index.tsx b/src/lib/pages/contract-details/components/tables/migration/index.tsx index 70d45e1bf..1f9d946bd 100644 --- a/src/lib/pages/contract-details/components/tables/migration/index.tsx +++ b/src/lib/pages/contract-details/components/tables/migration/index.tsx @@ -1,9 +1,8 @@ -import type { ChangeEvent } from "react"; - import { useMobile } from "lib/app-provider"; +import { Loading } from "lib/components/Loading"; import { Pagination } from "lib/components/pagination"; import { usePaginator } from "lib/components/pagination/usePaginator"; -import { EmptyState } from "lib/components/state"; +import { EmptyState, ErrorFetching } from "lib/components/state"; import { MobileTableContainer, TableContainer } from "lib/components/table"; import { useMigrationHistories } from "lib/pages/contract-details/data"; import type { ContractAddr, Option } from "lib/types"; @@ -42,26 +41,15 @@ export const MigrationTable = ({ }, }); - // TODO: loading state - const migrationHistories = useMigrationHistories( + const { data, isLoading, error } = useMigrationHistories( contractAddress, offset, pageSize ); - const onPageChange = (nextPage: number) => { - refetchCount(); - setCurrentPage(nextPage); - }; - - const onPageSizeChange = (e: ChangeEvent) => { - const size = Number(e.target.value); - refetchCount(); - setPageSize(size); - setCurrentPage(1); - }; - - if (!migrationHistories?.length) + if (isLoading) return ; + if (error) return ; + if (!data?.items.length) return ( {isMobile ? ( - {migrationHistories.map((history, idx) => ( + {data.items.map((history, idx) => ( - {migrationHistories.map((history, idx) => ( + {data.items.map((history, idx) => ( { + refetchCount(); + setCurrentPage(nextPage); + }} + onPageSizeChange={(e) => { + const size = Number(e.target.value); + refetchCount(); + setPageSize(size); + setCurrentPage(1); + }} /> )} diff --git a/src/lib/pages/contract-details/data.ts b/src/lib/pages/contract-details/data.ts index b1676c01a..ec2ee0038 100644 --- a/src/lib/pages/contract-details/data.ts +++ b/src/lib/pages/contract-details/data.ts @@ -12,13 +12,13 @@ import { queryContract, queryContractCw2Info } from "lib/services/contract"; import { useContractDetailByContractAddress, useInstantiateDetailByContractQuery, - useMigrationHistoriesByContractAddressPagination, + useMigrationHistoriesByContractAddress, } from "lib/services/contractService"; import { usePublicProjectByContractAddress, usePublicProjectBySlug, } from "lib/services/publicProjectService"; -import type { ContractAddr, ContractMigrationHistory, Option } from "lib/types"; +import type { ContractAddr, ContractMigrationHistory } from "lib/types"; import { coinToTokenWithValue, compareTokenWithValues } from "lib/utils"; import type { ContractData } from "./types"; @@ -101,22 +101,23 @@ export const useMigrationHistories = ( contractAddress: ContractAddr, offset: number, pageSize: number -): Option => { - const { data: migrationData } = - useMigrationHistoriesByContractAddressPagination( - contractAddress, - offset, - pageSize - ); +) => { const { getCodeLocalInfo } = useCodeStore(); + const { data, ...res } = useMigrationHistoriesByContractAddress( + contractAddress, + offset, + pageSize + ); - if (!migrationData) return undefined; - - return migrationData.map((data) => { - const localInfo = getCodeLocalInfo(data.codeId); - return { - ...data, - codeName: localInfo?.name, - }; - }); + return { + data: data + ? { + items: data.items.map((migration) => ({ + ...migration, + codeName: getCodeLocalInfo(migration.codeId)?.name, + })), + } + : undefined, + ...res, + }; }; diff --git a/src/lib/query/contract.ts b/src/lib/query/contract.ts index 899a788af..8ae577ad2 100644 --- a/src/lib/query/contract.ts +++ b/src/lib/query/contract.ts @@ -184,38 +184,6 @@ export const getContractListCountByCodeId = graphql(` } `); -export const getMigrationHistoriesByContractAddressPagination = graphql(` - query getMigrationHistoriesByContractAddress( - $contractAddress: String! - $offset: Int! - $pageSize: Int! - ) { - contract_histories( - where: { contract: { address: { _eq: $contractAddress } } } - order_by: { block: { timestamp: desc } } - limit: $pageSize - offset: $offset - ) { - code_id - account { - address - } - block { - height - timestamp - } - remark - code { - account { - address - } - cw2_contract - cw2_version - } - } - } -`); - export const getMigrationHistoriesCountByContractAddress = graphql(` query getMigrationHistoriesCountByContractAddress($contractAddress: String!) { contract_histories_aggregate( diff --git a/src/lib/services/account.ts b/src/lib/services/account.ts index 4847f3823..39576cdd2 100644 --- a/src/lib/services/account.ts +++ b/src/lib/services/account.ts @@ -28,7 +28,7 @@ export const getAccountInfo = async ( ): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/info`) - .then((res) => zAccountInfo.parse(res.data)); + .then(({ data }) => zAccountInfo.parse(data)); const zAccountTableCounts = z .object({ @@ -61,4 +61,4 @@ export const getAccountTableCounts = async ( is_wasm: isWasm, }, }) - .then((res) => zAccountTableCounts.parse(res.data)); + .then(({ data }) => zAccountTableCounts.parse(data)); diff --git a/src/lib/services/asset.ts b/src/lib/services/asset.ts index f4184d003..5df6b3b0c 100644 --- a/src/lib/services/asset.ts +++ b/src/lib/services/asset.ts @@ -14,4 +14,4 @@ export const getAssetInfos = async ( with_prices: withPrices, }, }) - .then((res) => z.array(zAssetInfo).parse(res.data)); + .then(({ data }) => z.array(zAssetInfo).parse(data)); diff --git a/src/lib/services/balance.ts b/src/lib/services/balance.ts index bacf6644d..8657450f9 100644 --- a/src/lib/services/balance.ts +++ b/src/lib/services/balance.ts @@ -19,4 +19,4 @@ export const getBalances = async ( ): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/balances`) - .then((res) => zBalancesResponse.parse(res.data)); + .then(({ data }) => zBalancesResponse.parse(data)); diff --git a/src/lib/services/block.ts b/src/lib/services/block.ts index 0a9c4752e..7f61a8e4e 100644 --- a/src/lib/services/block.ts +++ b/src/lib/services/block.ts @@ -54,7 +54,7 @@ export const getBlocks = async ( offset, }, }) - .then((res) => zBlocksResponse.parse(res.data)); + .then(({ data }) => zBlocksResponse.parse(data)); const zBlockDataResponse = z .object({ @@ -77,4 +77,4 @@ const zBlockDataResponse = z export const getBlockData = async (endpoint: string, height: number) => axios .get(`${endpoint}/${height}/info`) - .then((res) => zBlockDataResponse.parse(res.data)); + .then(({ data }) => zBlockDataResponse.parse(data)); diff --git a/src/lib/services/code.ts b/src/lib/services/code.ts index 248837306..1e9210bc1 100644 --- a/src/lib/services/code.ts +++ b/src/lib/services/code.ts @@ -72,4 +72,4 @@ export const getCodesByAddress = async ( offset, }, }) - .then((res) => zCodesResponse.parse(res.data)); + .then(({ data }) => zCodesResponse.parse(data)); diff --git a/src/lib/services/contract.ts b/src/lib/services/contract.ts index 64290963f..78c137296 100644 --- a/src/lib/services/contract.ts +++ b/src/lib/services/contract.ts @@ -7,10 +7,14 @@ import type { Option, PublicInfo, ContractInfo, - ContractHistoryRemark, - RemarkType, + ContractMigrationHistory, +} from "lib/types"; +import { + zAddr, + zContractAddr, + zContractHistoryRemark, + zUtcDate, } from "lib/types"; -import { RemarkOperation, zAddr, zContractAddr, zUtcDate } from "lib/types"; import { encode, libDecode } from "lib/utils"; export interface ContractCw2InfoRaw { @@ -105,17 +109,7 @@ const zContractsResponseItem = z instantiator: zAddr, latest_updated: zUtcDate, latest_updater: zAddr, - remark: z - .object({ - operation: z.nativeEnum(RemarkOperation), - type: z.string(), - value: z.string(), - }) - .transform((val) => ({ - operation: val.operation, - type: val.type as RemarkType, // TODO: remove type assertion, - value: val.value, - })), + remark: zContractHistoryRemark, }) .transform((val) => ({ contractAddress: val.contract_address, @@ -166,3 +160,48 @@ export const getAdminContractsByAddress = async ( }, }) .then(({ data }) => zContractsResponse.parse(data)); + +const zMigrationHistoriesResponseItem = z + .object({ + code_id: z.number(), + cw2_contract: z.string().nullable(), + cw2_version: z.string().nullable(), + height: z.number(), + remark: zContractHistoryRemark, + sender: zAddr, + timestamp: zUtcDate, + uploader: zAddr, + }) + .transform((val) => ({ + codeId: val.code_id, + cw2Contract: val.cw2_contract, + cw2Version: val.cw2_version, + height: val.height, + remark: val.remark, + sender: val.sender, + timestamp: val.timestamp, + uploader: val.uploader, + })); + +const zMigrationHistoriesResponse = z.object({ + items: z.array(zMigrationHistoriesResponseItem), +}); + +export type MigrationHistoriesResponse = z.infer< + typeof zMigrationHistoriesResponse +>; + +export const getMigrationHistoriesByContractAddress = async ( + endpoint: string, + contractAddress: ContractAddr, + limit: number, + offset: number +) => + axios + .get(`${endpoint}/${encodeURIComponent(contractAddress)}/migrations`, { + params: { + limit, + offset, + }, + }) + .then(({ data }) => zMigrationHistoriesResponse.parse(data)); diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts index 2a9b27bb7..953b184a0 100644 --- a/src/lib/services/contractService.ts +++ b/src/lib/services/contractService.ts @@ -22,14 +22,12 @@ import { getInstantiatedCountByUserQueryDocument, getInstantiateDetailByContractQueryDocument, getInstantiatedListByUserQueryDocument, - getMigrationHistoriesByContractAddressPagination, getMigrationHistoriesCountByContractAddress, } from "lib/query"; import { createQueryFnWithTimeout } from "lib/query-utils"; import type { ContractLocalInfo } from "lib/stores/contract"; import type { ContractAddr, - ContractMigrationHistory, HumanAddr, Option, Dict, @@ -37,13 +35,14 @@ import type { ContractInfo, Nullable, } from "lib/types"; -import { parseDate, parseTxHashOpt, parseDateOpt } from "lib/utils"; +import { parseTxHashOpt, parseDateOpt } from "lib/utils"; import { getCodeIdInfo } from "./code"; +import type { ContractsResponse, MigrationHistoriesResponse } from "./contract"; import { - type ContractsResponse, getAdminContractsByAddress, getInstantiatedContractsByAddress, + getMigrationHistoriesByContractAddress, } from "./contract"; export interface ContractDetail extends ContractLocalInfo { @@ -308,48 +307,31 @@ export const useAdminByContractAddresses = ( ); }; -export const useMigrationHistoriesByContractAddressPagination = ( +export const useMigrationHistoriesByContractAddress = ( contractAddress: ContractAddr, offset: number, - pageSize: number -): UseQueryResult[]> => { - const { indexerGraphClient } = useCelatoneApp(); - - const queryFn = useCallback(async () => { - return indexerGraphClient - .request(getMigrationHistoriesByContractAddressPagination, { - contractAddress, - offset, - pageSize, - }) - .then(({ contract_histories }) => - contract_histories.map>( - (history) => ({ - codeId: history.code_id, - sender: history.account.address as Addr, - height: history.block.height, - timestamp: parseDate(history.block.timestamp), - remark: history.remark, - uploader: history.code.account.address as Addr, - cw2Contract: history.code.cw2_contract, - cw2Version: history.code.cw2_version, - }) - ) - ); - }, [contractAddress, offset, pageSize, indexerGraphClient]); + limit: number +) => { + const endpoint = useBaseApiRoute("contracts"); - return useQuery( + return useQuery( [ - CELATONE_QUERY_KEYS.CONTRACT_MIGRATION_HISTORIES_PAGINATION, + CELATONE_QUERY_KEYS.CONTRACT_MIGRATION_HISTORIES, + endpoint, contractAddress, + limit, offset, - pageSize, - indexerGraphClient, ], - queryFn, + async () => + getMigrationHistoriesByContractAddress( + endpoint, + contractAddress, + limit, + offset + ), { keepPreviousData: true, - enabled: Boolean(contractAddress), + retry: 1, } ); }; diff --git a/src/lib/services/delegation.ts b/src/lib/services/delegation.ts index 15fda6a46..5d29e37ef 100644 --- a/src/lib/services/delegation.ts +++ b/src/lib/services/delegation.ts @@ -339,4 +339,4 @@ export const getAccountDelegations = async ( ): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/delegations`) - .then((res) => zAccountDelegations.parse(res.data)); + .then(({ data }) => zAccountDelegations.parse(data)); diff --git a/src/lib/services/move/module.ts b/src/lib/services/move/module.ts index 7b3615b5a..c861cae80 100644 --- a/src/lib/services/move/module.ts +++ b/src/lib/services/move/module.ts @@ -51,7 +51,7 @@ export const getAPIAccountModules = async ( ): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/move/modules`) - .then((res) => zAccountModulesResponse.parse(res.data)); + .then(({ data }) => zAccountModulesResponse.parse(data)); export const getAccountModules = async ( baseEndpoint: string, @@ -196,4 +196,4 @@ export const getModules = async ( offset, }, }) - .then((res) => zModulesResponse.parse(res.data)); + .then(({ data }) => zModulesResponse.parse(data)); diff --git a/src/lib/services/move/pool.ts b/src/lib/services/move/pool.ts index 0a0e8d845..d15992d04 100644 --- a/src/lib/services/move/pool.ts +++ b/src/lib/services/move/pool.ts @@ -43,4 +43,4 @@ const zPairResponse = z export const getMovePoolInfos = async (endpoint: string) => axios .get(`${endpoint}/pools`) - .then((res) => z.array(zPairResponse).parse(res.data)); + .then(({ data }) => z.array(zPairResponse).parse(data)); diff --git a/src/lib/services/move/resource.ts b/src/lib/services/move/resource.ts index 8d5e322f9..08d914c12 100644 --- a/src/lib/services/move/resource.ts +++ b/src/lib/services/move/resource.ts @@ -29,4 +29,4 @@ export const getAccountResources = async ( ): Promise => axios .get(`${endpoint}/${encodeURIComponent(address)}/move/resources`) - .then((res) => zResourcesResponse.parse(res.data)); + .then(({ data }) => zResourcesResponse.parse(data)); diff --git a/src/lib/services/overview.ts b/src/lib/services/overview.ts index 1b0381635..03919207c 100644 --- a/src/lib/services/overview.ts +++ b/src/lib/services/overview.ts @@ -20,4 +20,4 @@ export const getOverviewsStats = async ( ): Promise => axios .get(`${endpoint}/stats`) - .then((res) => zOverviewsStatsResponse.parse(res.data)); + .then(({ data }) => zOverviewsStatsResponse.parse(data)); diff --git a/src/lib/services/proposal.ts b/src/lib/services/proposal.ts index 8ccd78c8e..44e1a0be3 100644 --- a/src/lib/services/proposal.ts +++ b/src/lib/services/proposal.ts @@ -108,7 +108,7 @@ export const getProposalsByAddress = async ( offset, }, }) - .then((res) => zProposalsResponse.parse(res.data)); + .then(({ data }) => zProposalsResponse.parse(data)); const zRelatedProposalsResponseItem = z .object({ @@ -158,4 +158,4 @@ export const getRelatedProposalsByContractAddress = async ( }, } ) - .then((res) => zRelatedProposalsResponse.parse(res.data)); + .then(({ data }) => zRelatedProposalsResponse.parse(data)); diff --git a/src/lib/services/tx.ts b/src/lib/services/tx.ts index ab4af4f96..b8fa5d7ba 100644 --- a/src/lib/services/tx.ts +++ b/src/lib/services/tx.ts @@ -179,7 +179,7 @@ export const getTxs = async ( is_initia: isInitia, }, }) - .then((res) => zTxsResponse.parse(res.data)); + .then(({ data }) => zTxsResponse.parse(data)); const zAccountTxsResponseItem = zBaseTxsResponseItem .extend({ @@ -259,7 +259,7 @@ export const getTxsByAddress = async ( ...(search !== undefined && { search }), }, }) - .then((res) => zAccountTxsResponse.parse(res.data)); + .then(({ data }) => zAccountTxsResponse.parse(data)); }; const zBlockTxsResponse = z.object({ @@ -287,7 +287,7 @@ export const getTxsByBlockHeight = async ( is_initia: isInitia, }, }) - .then((res) => zBlockTxsResponse.parse(res.data)); + .then(({ data }) => zBlockTxsResponse.parse(data)); const zModuleTxsResponse = z.object({ items: z.array(zTxsResponseItem), @@ -317,7 +317,7 @@ export const getTxsByModule = async ( }, } ) - .then((res) => zModuleTxsResponse.parse(res.data)); + .then(({ data }) => zModuleTxsResponse.parse(data)); const zTxsCountResponse = z .object({ @@ -344,5 +344,5 @@ export const getAPITxsCountByAddress = async ( ...(search !== undefined && { search }), }, }) - .then((res) => zTxsCountResponse.parse(res.data)); + .then(({ data }) => zTxsCountResponse.parse(data)); }; diff --git a/src/lib/types/contract.ts b/src/lib/types/contract.ts index 249be4e80..03693d2da 100644 --- a/src/lib/types/contract.ts +++ b/src/lib/types/contract.ts @@ -1,5 +1,10 @@ +import { z } from "zod"; + import type { ContractLocalInfo } from "lib/stores/contract"; -import type { Addr, Nullable, Option, RemarkType } from "lib/types"; + +import type { Addr } from "./addrs"; +import type { Nullable, Option } from "./common"; +import { zRemarkType } from "./tx"; export enum RemarkOperation { CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT = "CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT", @@ -7,11 +12,13 @@ export enum RemarkOperation { CONTRACT_CODE_HISTORY_OPERATION_TYPE_GENESIS = "CONTRACT_CODE_HISTORY_OPERATION_TYPE_GENESIS", } -export interface ContractHistoryRemark { - operation: RemarkOperation; - type: RemarkType; - value: string | number; -} +export const zContractHistoryRemark = z.object({ + operation: z.nativeEnum(RemarkOperation), + type: zRemarkType, + value: z.union([z.string(), z.number()]), +}); + +export type ContractHistoryRemark = z.infer; export interface ContractInfo extends ContractLocalInfo { admin: Option; @@ -28,6 +35,6 @@ export interface ContractMigrationHistory { timestamp: Date; remark: ContractHistoryRemark; uploader: Addr; - cw2Contract: Option>; - cw2Version: Option>; + cw2Contract: Nullable; + cw2Version: Nullable; } diff --git a/src/lib/types/tx/transaction.ts b/src/lib/types/tx/transaction.ts index 0507c8ad0..256fdb0e3 100644 --- a/src/lib/types/tx/transaction.ts +++ b/src/lib/types/tx/transaction.ts @@ -1,4 +1,5 @@ import type { Log } from "@cosmjs/stargate/build/logs"; +import { z } from "zod"; import type { Addr, Option } from "lib/types"; @@ -81,4 +82,5 @@ export type PoolTxFilter = | "is_collect" | "is_migrate"; -export type RemarkType = "genesis" | "governance" | "transaction"; +export const zRemarkType = z.enum(["genesis", "governance", "transaction"]); +export type RemarkType = z.infer; From a1babf0682251102b084b510ae7989391a34f9f3 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:10:44 +0700 Subject: [PATCH 3/6] fix: revert file --- src/lib/app-provider/hooks/useBaseApiRoute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/app-provider/hooks/useBaseApiRoute.ts b/src/lib/app-provider/hooks/useBaseApiRoute.ts index 6ada0d430..e52f774f3 100644 --- a/src/lib/app-provider/hooks/useBaseApiRoute.ts +++ b/src/lib/app-provider/hooks/useBaseApiRoute.ts @@ -46,7 +46,7 @@ export const useBaseApiRoute = ( case "projects": return `${api}/projects/${chain}/${currentChainId}`; case "contracts": - return `${api}/v1/${chain}/${currentChainId}/contracts`; + return `${api}/contracts/${chain}/${currentChainId}`; case "codes": return `${api}/codes/${chain}/${currentChainId}`; case "legacy.accounts": From d6d795e71b8d5a3a928e2e2b7138a96cb083d24c Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Sun, 24 Dec 2023 02:14:03 +0700 Subject: [PATCH 4/6] fix: rename query key --- src/lib/app-provider/env.ts | 2 +- src/lib/services/contractService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/app-provider/env.ts b/src/lib/app-provider/env.ts index acb633529..51251db24 100644 --- a/src/lib/app-provider/env.ts +++ b/src/lib/app-provider/env.ts @@ -45,7 +45,7 @@ export enum CELATONE_QUERY_KEYS { INSTANTIATED_LIST_BY_WALLET_ADDRESS = "CELATONE_QUERY_INSTANTIATED_LIST_BY_WALLET_ADDRESS", ADMIN_CONTRACTS_BY_ADDRESS = "CELATONE_QUERY_ADMIN_CONTRACTS_BY_ADDRESS", ADMINS_BY_CONTRACTS = "CELATONE_QUERY_ADMINS_BY_CONTRACTS", - CONTRACT_MIGRATION_HISTORIES = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES", + CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS", CONTRACT_MIGRATION_HISTORIES_COUNT = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_COUNT", CONTRACTS_BY_CODE_ID_PAGINATION = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_PAGINATION", CONTRACTS_BY_CODE_ID_COUNT = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_COUNT", diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts index 953b184a0..66609b307 100644 --- a/src/lib/services/contractService.ts +++ b/src/lib/services/contractService.ts @@ -316,7 +316,7 @@ export const useMigrationHistoriesByContractAddress = ( return useQuery( [ - CELATONE_QUERY_KEYS.CONTRACT_MIGRATION_HISTORIES, + CELATONE_QUERY_KEYS.CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS, endpoint, contractAddress, limit, From 9d6a67dc19d231c0d8a6d57471e68d3a31118b17 Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:04:51 +0700 Subject: [PATCH 5/6] fix: remove unused query key --- src/lib/app-provider/env.ts | 1 - src/lib/pages/contract-details/data.ts | 2 +- src/lib/services/contract.ts | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/app-provider/env.ts b/src/lib/app-provider/env.ts index 21c63432f..95163c888 100644 --- a/src/lib/app-provider/env.ts +++ b/src/lib/app-provider/env.ts @@ -43,7 +43,6 @@ export enum CELATONE_QUERY_KEYS { INSTANTIATED_LIST_BY_WALLET_ADDRESS = "CELATONE_QUERY_INSTANTIATED_LIST_BY_WALLET_ADDRESS", ADMINS_BY_CONTRACTS = "CELATONE_QUERY_ADMINS_BY_CONTRACTS", CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS", - CONTRACT_MIGRATION_HISTORIES_COUNT = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_COUNT", CONTRACTS_BY_CODE_ID_PAGINATION = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_PAGINATION", CONTRACTS_BY_CODE_ID_COUNT = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_COUNT", // X/STAKING diff --git a/src/lib/pages/contract-details/data.ts b/src/lib/pages/contract-details/data.ts index ec2ee0038..10198afa0 100644 --- a/src/lib/pages/contract-details/data.ts +++ b/src/lib/pages/contract-details/data.ts @@ -102,12 +102,12 @@ export const useMigrationHistories = ( offset: number, pageSize: number ) => { - const { getCodeLocalInfo } = useCodeStore(); const { data, ...res } = useMigrationHistoriesByContractAddress( contractAddress, offset, pageSize ); + const { getCodeLocalInfo } = useCodeStore(); return { data: data diff --git a/src/lib/services/contract.ts b/src/lib/services/contract.ts index 9dc2ac585..0fec49158 100644 --- a/src/lib/services/contract.ts +++ b/src/lib/services/contract.ts @@ -176,6 +176,7 @@ export const getMigrationHistoriesByContractAddress = async ( }, }) .then(({ data }) => zMigrationHistoriesResponse.parse(data)); + const zContractTableCounts = z .object({ tx: z.number().nullish(), From c26a5880520c8ded499e7f546ba64cfae496f4da Mon Sep 17 00:00:00 2001 From: songwongtp <16089160+songwongtp@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:53:42 +0700 Subject: [PATCH 6/6] fix: comment --- .../components/tables/migration/RemarkRender.tsx | 5 +++-- src/lib/services/contract.ts | 2 +- src/lib/services/proposal.ts | 11 +++++------ src/lib/types/contract.ts | 2 +- src/lib/types/proposal.ts | 12 ++++++++---- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/lib/pages/contract-details/components/tables/migration/RemarkRender.tsx b/src/lib/pages/contract-details/components/tables/migration/RemarkRender.tsx index ec09ae880..f692bb46e 100644 --- a/src/lib/pages/contract-details/components/tables/migration/RemarkRender.tsx +++ b/src/lib/pages/contract-details/components/tables/migration/RemarkRender.tsx @@ -1,5 +1,5 @@ import { Flex, Text } from "@chakra-ui/react"; -import { capitalize } from "lodash"; +import { capitalize, isUndefined } from "lodash"; import { ExplorerLink } from "lib/components/ExplorerLink"; import type { ContractMigrationHistory } from "lib/types"; @@ -10,7 +10,8 @@ export const RemarkRender = ({ remark: ContractMigrationHistory["remark"]; }) => { const { operation, type, value } = remark; - if (type === "genesis") return Genesis; + if (type === "genesis" || isUndefined(value)) + return Genesis; const isGovernance = type === "governance"; const prefix = capitalize(operation.split("_").pop()); diff --git a/src/lib/services/contract.ts b/src/lib/services/contract.ts index 0fec49158..5db7e015c 100644 --- a/src/lib/services/contract.ts +++ b/src/lib/services/contract.ts @@ -134,7 +134,7 @@ export const getAdminContractsByAddress = async ( const zMigrationHistoriesResponseItem = z .object({ - code_id: z.number(), + code_id: z.number().positive(), cw2_contract: z.string().nullable(), cw2_version: z.string().nullable(), height: z.number(), diff --git a/src/lib/services/proposal.ts b/src/lib/services/proposal.ts index 44e1a0be3..40bebceba 100644 --- a/src/lib/services/proposal.ts +++ b/src/lib/services/proposal.ts @@ -2,14 +2,13 @@ import type { Coin } from "@cosmjs/stargate"; import axios from "axios"; import { z } from "zod"; -import { zAddr, zUtcDate } from "lib/types"; +import { zAddr, zUtcDate, zProposalType } from "lib/types"; import type { ContractAddr, AccessConfigPermission, Addr, SnakeToCamelCaseNested, Proposal, - ProposalType, } from "lib/types"; import { parseProposalStatus, snakeToCamel } from "lib/utils"; @@ -73,7 +72,7 @@ const zProposalsResponseItem = z resolved_height: z.number().nullish(), status: z.string().transform(parseProposalStatus), title: z.string(), - type: z.string(), + type: zProposalType, voting_end_time: zUtcDate, }) .transform((val) => ({ @@ -84,7 +83,7 @@ const zProposalsResponseItem = z resolvedHeight: val.resolved_height, status: val.status, title: val.title, - type: val.type as ProposalType, // TODO: remove type assertion + type: val.type, votingEndTime: val.voting_end_time, })); @@ -119,7 +118,7 @@ const zRelatedProposalsResponseItem = z resolved_height: z.number().nullish(), status: z.string().transform(parseProposalStatus), title: z.string(), - type: z.string(), + type: zProposalType, voting_end_time: zUtcDate, }) .transform((val) => ({ @@ -130,7 +129,7 @@ const zRelatedProposalsResponseItem = z resolvedHeight: val.resolved_height, status: val.status, title: val.title, - type: val.type as ProposalType, // TODO: remove type assertion + type: val.type, votingEndTime: val.voting_end_time, })); diff --git a/src/lib/types/contract.ts b/src/lib/types/contract.ts index 03693d2da..29ff4516b 100644 --- a/src/lib/types/contract.ts +++ b/src/lib/types/contract.ts @@ -15,7 +15,7 @@ export enum RemarkOperation { export const zContractHistoryRemark = z.object({ operation: z.nativeEnum(RemarkOperation), type: zRemarkType, - value: z.union([z.string(), z.number()]), + value: z.union([z.string(), z.number()]).optional(), }); export type ContractHistoryRemark = z.infer; diff --git a/src/lib/types/proposal.ts b/src/lib/types/proposal.ts index 24aaf3c89..5e6db17fc 100644 --- a/src/lib/types/proposal.ts +++ b/src/lib/types/proposal.ts @@ -1,3 +1,5 @@ +import { z } from "zod"; + import type { Addr, Nullable, Option } from "lib/types"; export enum ProposalStatus { @@ -44,10 +46,12 @@ enum ProposalTypeOsmosis { SET_PROTOREV_ADMIN_ACCOUNT = "SetProtoRevAdminAccount", } -export type ProposalType = - | ProposalTypeCosmos - | ProposalTypeCosmWasm - | ProposalTypeOsmosis; +export const zProposalType = z.union([ + z.nativeEnum(ProposalTypeCosmos), + z.nativeEnum(ProposalTypeCosmWasm), + z.nativeEnum(ProposalTypeOsmosis), +]); +export type ProposalType = z.infer; export interface Proposal { proposalId: number;