Skip to content

Commit

Permalink
Merge pull request #969 from alleslabs/fix/contract-details
Browse files Browse the repository at this point in the history
  • Loading branch information
evilpeach committed Jun 13, 2024
2 parents e31e2cc + 41b714f commit ac18786
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 63 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Bug fixes

- [#969](https://github.com/alleslabs/celatone-frontend/pull/969) Fix contract data lcd missing data
- [#890](https://github.com/alleslabs/celatone-frontend/pull/890) Fix tomcat pretty name
- [#889](https://github.com/alleslabs/celatone-frontend/pull/889) Fix overflow validator table header
- [#886](https://github.com/alleslabs/celatone-frontend/pull/886) Fix tx detail message newline
Expand Down
3 changes: 2 additions & 1 deletion src/lib/app-provider/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export enum CELATONE_QUERY_KEYS {
CONTRACT_DATA = "CELATONE_QUERY_CONTRACT_DATA",
CONTRACT_QUERY_MSGS = "CELATONE_QUERY_CONTRACT_QUERY_MSGS",
CONTRACT_QUERY_LCD = "CELATONE_QUERY_CONTRACT_QUERY_LCD",
CONTRACT_STATES = "CELATONE_QUERY_CONTRACT_STATES",
CONTRACT_STATES_LCD = "CELATONE_QUERY_CONTRACT_STATES_LCD",
CONTRACTS_BY_CODE_ID = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID",
CONTRACTS_BY_CODE_ID_LCD = "CELATONE_QUERY_CONTRACTS_BY_CODE_ID_LCD",
CONTRACTS_BY_ADMIN = "CELATONE_QUERY_CONTRACT_BY_ADMIN",
Expand All @@ -46,6 +46,7 @@ export enum CELATONE_QUERY_KEYS {
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_BY_CONTRACT_ADDRESS_LCD = "CELATONE_QUERY_CONTRACT_MIGRATION_HISTORIES_BY_CONTRACT_ADDRESS_LCD",
CONTRACT_CW2_INFO_LCD = "CELATONE_QUERY_CONTRACT_CW2_INFO_LCD",
// X/STAKING
STAKING_PARAMS_LCD = "CELATONE_QUERY_STAKING_PARAMS_LCD",
DELEGATIONS_BY_ADDRESS_LCD = "CELATONE_QUERY_DELEGATIONS_BY_ADDRESS_LCD",
Expand Down
28 changes: 20 additions & 8 deletions src/lib/pages/contract-details/components/InstantiateInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,27 @@ export const InstantiateInfo = ({
<LabelText
flex="1"
label="Instantiated Block Height"
helperText1={formatUTC(contract.createdTimestamp)}
helperText2={dateFromNow(contract.createdTimestamp)}
helperText1={
contract.createdTimestamp
? formatUTC(contract.createdTimestamp)
: undefined
}
helperText2={
contract.createdTimestamp
? dateFromNow(contract.createdTimestamp)
: undefined
}
>
<ExplorerLink
type="block_height"
value={contract.createdHeight.toString()}
showCopyOnHover
fixedHeight
/>
{contract.createdHeight ? (
<ExplorerLink
type="block_height"
value={contract.createdHeight.toString()}
showCopyOnHover
fixedHeight
/>
) : (
"N/A"
)}
</LabelText>
<Flex direction={{ base: "row", md: "column" }} gap={{ base: 1, md: 6 }}>
<LabelText
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useMemo, useState } from "react";

import { AmpEvent, track, trackContractStatesLoad } from "lib/amplitude";
import InputWithIcon from "lib/components/InputWithIcon";
import { useContractStates } from "lib/services/contractStateService";
import { useContractStatesLcd } from "lib/services/wasm/contractState";
import type { BechAddr32 } from "lib/types";
import { groupContractStatesByFirstIndex } from "lib/utils";

Expand All @@ -29,7 +29,7 @@ interface ContractStatesProps {
contractAddress: BechAddr32;
}

const NUM_STATES_TO_LOAD = 100;
const limit = 100;

export const ContractStates = ({ contractAddress }: ContractStatesProps) => {
const {
Expand All @@ -39,7 +39,7 @@ export const ContractStates = ({ contractAddress }: ContractStatesProps) => {
hasNextPage,
isFetching,
isFetchingNextPage,
} = useContractStates(contractAddress, NUM_STATES_TO_LOAD);
} = useContractStatesLcd(contractAddress, limit);

const [selectedNamespace, setSelectedNamespace] = useState("all");
const [keyword, setKeyword] = useState("");
Expand Down Expand Up @@ -95,7 +95,7 @@ export const ContractStates = ({ contractAddress }: ContractStatesProps) => {
Contract States
</Heading>
<StateLoader
numStatesToLoad={NUM_STATES_TO_LOAD}
numStatesToLoad={limit}
isLoading={isFetching || isFetchingNextPage}
totalData={totalData}
isCompleted={!hasNextPage}
Expand Down
48 changes: 47 additions & 1 deletion src/lib/pages/contract-details/data.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
import type { UseQueryResult } from "@tanstack/react-query";

import { useTierConfig } from "lib/app-provider";
import { useCodeStore, useContractStore } from "lib/providers/store";
import type { ContractData } from "lib/services/types";
import { useCodeLcd } from "lib/services/wasm/code";
import {
useContractCw2InfoLcd,
useContractData,
useMigrationHistoriesByContractAddress,
useMigrationHistoriesByContractAddressLcd,
} from "lib/services/wasm/contract";
import { RemarkOperation } from "lib/types";
import type { BechAddr32, ContractMigrationHistory } from "lib/types";

const useContractDataLcd = (
contractData: UseQueryResult<ContractData>,
contractAddress: BechAddr32
) => {
const isFullTier = useTierConfig() === "full";

const { data: code } = useCodeLcd(
Number(contractData.data?.contract.codeId),
{
enabled: !isFullTier && !!contractData.data?.contract.codeId,
}
);
const { data: cw2Info } = useContractCw2InfoLcd(contractAddress, !isFullTier);
const { data: migrationHistories } =
useMigrationHistoriesByContractAddressLcd(contractAddress, !isFullTier);

return !isFullTier && contractData.data
? {
...contractData,
data: {
...contractData.data,
contract: {
...contractData.data.contract,
codeHash: code?.hash ?? "",
cw2Contract: cw2Info?.contract ?? null,
cw2Version: cw2Info?.version ?? null,
initMsg:
migrationHistories?.entries.find(
(history) =>
history.remark?.operation ===
RemarkOperation.CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT
)?.msg ?? "",
},
},
}
: contractData;
};

export const useContractDataWithLocalInfos = (contractAddress: BechAddr32) => {
const { getCodeLocalInfo } = useCodeStore();
const { getContractLocalInfo } = useContractStore();

const result = useContractData(contractAddress);
let result = useContractData(contractAddress);
result = useContractDataLcd(result, contractAddress);

const codeLocalInfo = result.data?.contract
? getCodeLocalInfo(Number(result.data.contract.codeId))
Expand Down
47 changes: 30 additions & 17 deletions src/lib/services/types/wasm/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@ import z from "zod";

import type { ContractInfo, ContractMigrationHistory } from "lib/types";
import {
RemarkOperation,
zBechAddr,
zBechAddr32,
zContractHistoryRemark,
zPagination,
zProjectInfo,
zPublicContractInfo,
zRemarkOperation,
zUtcDate,
} from "lib/types";
import { getDefaultDate, parseTxHash, snakeToCamel } from "lib/utils";

export interface ContractCw2Info {
contract: string;
version: string;
}
import { decode, parseTxHash, snakeToCamel } from "lib/utils";

const zContractCreated = z.object({
block_height: z.coerce.number(),
Expand All @@ -30,7 +25,7 @@ const zContractRest = z.object({
creator: zBechAddr,
admin: z.string(),
label: z.string(),
created: zContractCreated,
created: zContractCreated.nullable(),
ibc_port_id: z.string(),
extension: z.string().nullable(),
}),
Expand Down Expand Up @@ -94,8 +89,8 @@ export const zContract = z
admin: zBechAddr.nullable(),
code_id: z.number().positive(),
code_hash: z.string().transform(parseTxHash),
created_height: z.number(),
created_timestamp: zUtcDate,
created_height: z.number().nullable(),
created_timestamp: zUtcDate.nullable(),
cw2_contract: z.string().nullable(),
cw2_version: z.string().nullable(),
init_msg: z.string(),
Expand Down Expand Up @@ -128,14 +123,13 @@ export const zContractLcd = zContractRest.transform<ContractData>((val) => ({
? zBechAddr.parse(val.contract_info.admin)
: null,
codeId: Number(val.contract_info.code_id),
// TODO: make optional - get from code
codeHash: "",
createdHeight: Number(val.contract_info.created.block_height),
// TODO: make optional
createdTimestamp: getDefaultDate(),
createdHeight: val.contract_info.created
? Number(val.contract_info.created.block_height)
: null,
createdTimestamp: null,
cw2Contract: null,
cw2Version: null,
// TODO: make optional - get from histories
initMsg: "",
initProposalId: null,
initProposalTitle: null,
Expand Down Expand Up @@ -188,20 +182,25 @@ export const zContractQueryMsgs = z

export const zMigrationHistoriesResponseItemLcd = z
.object({
operation: z.nativeEnum(RemarkOperation),
operation: zRemarkOperation,
code_id: z.coerce.number().positive(),
updated: zContractCreated,
msg: z.object({}).passthrough(),
})
.transform<ContractMigrationHistory>((val) => ({
codeId: val.code_id,
codeName: undefined,
height: Number(val.updated.block_height),
timestamp: null,
uploader: null,
remark: null,
remark: {
operation: val.operation,
type: null,
},
sender: null,
cw2Contract: null,
cw2Version: null,
msg: JSON.stringify(val.msg),
}));
export type MigrationHistoriesResponseItemLcd = z.infer<
typeof zMigrationHistoriesResponseItemLcd
Expand All @@ -220,3 +219,17 @@ export const zInstantiatedContractsLcd = z
contract_addresses: zBechAddr32.array(),
})
.transform(snakeToCamel);

export const zContractCw2InfoLcd = z
.object({
data: z.string(),
})
.transform((val) => JSON.parse(decode(val.data)))
.pipe(
z.object({
contract: z.string(),
version: z.string(),
})
);

export type ContractCw2InfoLcd = z.infer<typeof zContractCw2InfoLcd>;
13 changes: 13 additions & 0 deletions src/lib/services/types/wasm/contractState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from "zod";

import { zPagination } from "lib/types";

export const zResponseContractState = z.object({
key: z.string(),
value: z.string(),
});

export const zResponseContractStates = z.object({
models: zResponseContractState.array(),
pagination: zPagination,
});
1 change: 1 addition & 0 deletions src/lib/services/types/wasm/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./code";
export * from "./contract";
export * from "./contractState";
18 changes: 17 additions & 1 deletion src/lib/services/wasm/contract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
getMigrationHistoriesByContractAddress,
} from "./api";
import {
getContractCw2InfoLcd,
getContractLcd,
getContractQueryLcd,
getContractQueryMsgsLcd,
Expand Down Expand Up @@ -89,7 +90,8 @@ export const useMigrationHistoriesByContractAddress = (
};

export const useMigrationHistoriesByContractAddressLcd = (
contractAddress: BechAddr32
contractAddress: BechAddr32,
enabled = true
) => {
const endpoint = useLcdEndpoint();

Expand All @@ -104,6 +106,7 @@ export const useMigrationHistoriesByContractAddressLcd = (
{
retry: 1,
keepPreviousData: true,
enabled,
}
);
};
Expand Down Expand Up @@ -269,4 +272,17 @@ export const useInstantiatedContractsByAddressLcd = (
);
};

export const useContractCw2InfoLcd = (
contractAddress: BechAddr32,
enabled = true
) => {
const endpoint = useLcdEndpoint();

return useQuery(
[CELATONE_QUERY_KEYS.CONTRACT_CW2_INFO_LCD, endpoint, contractAddress],
async () => getContractCw2InfoLcd(endpoint, contractAddress),
{ retry: 1, refetchOnWindowFocus: false, enabled }
);
};

export * from "./gql";
12 changes: 12 additions & 0 deletions src/lib/services/wasm/contract/lcd.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import axios from "axios";

import type {
ContractCw2InfoLcd,
MigrationHistoriesResponseItemLcd,
MigrationHistoriesResponseLcd,
} from "lib/services/types";
import {
zContractCw2InfoLcd,
zContractLcd,
zContractQueryMsgs,
zContractsResponseLcd,
Expand Down Expand Up @@ -150,3 +152,13 @@ export const getInstantiatedContractsByAddressLcd = (
label: "",
}));
});

export const getContractCw2InfoLcd = async (
endpoint: string,
contractAddress: BechAddr32
): Promise<ContractCw2InfoLcd> =>
axios
.get(
`${endpoint}/cosmwasm/wasm/v1/contract/${encodeURI(contractAddress)}/raw/Y29udHJhY3RfaW5mbw%3D%3D`
)
.then(({ data }) => parseWithError(zContractCw2InfoLcd, data));
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { useInfiniteQuery } from "@tanstack/react-query";

import { CELATONE_QUERY_KEYS, useBaseApiRoute } from "lib/app-provider";
import { CELATONE_QUERY_KEYS, useLcdEndpoint } from "lib/app-provider";
import type { BechAddr32 } from "lib/types";

import { getContractStates } from "./contractState";
import { getContractStatesLcd } from "./lcd";

export const useContractStates = (
export const useContractStatesLcd = (
contractAddress: BechAddr32,
numStatesToLoad: number
) => {
const baseEndpoint = useBaseApiRoute("contracts");
const lcdEndpoint = useLcdEndpoint();

return useInfiniteQuery(
[
CELATONE_QUERY_KEYS.CONTRACT_STATES,
baseEndpoint,
CELATONE_QUERY_KEYS.CONTRACT_STATES_LCD,
lcdEndpoint,
contractAddress,
numStatesToLoad,
],
({ pageParam }) =>
getContractStates(
baseEndpoint,
getContractStatesLcd(
lcdEndpoint,
contractAddress,
numStatesToLoad,
pageParam
Expand Down
Loading

0 comments on commit ac18786

Please sign in to comment.