+) => {
const { data: codesCount, refetch: refetchCodesCount } =
useCodeListCountByWalletAddress(walletAddress);
const { data: contractsAdminCount, refetch: refetchContractsAdminCount } =
@@ -23,8 +26,9 @@ export const useAccountDetailsTableCounts = (walletAddress: HumanAddr) => {
useInstantiatedCountByUserQuery(walletAddress);
const { data: proposalsCount, refetch: refetchProposalsCount } =
useProposalsCountByWalletAddress(walletAddress);
- const { data: txsCount, refetch: refetchTxsCount } = useTxsCountByAddress(
- walletAddress,
+ const { data: txsCount } = useTxsCountByAddress(
+ undefined,
+ accountId,
"",
DEFAULT_TX_FILTERS,
undefined
@@ -44,7 +48,6 @@ export const useAccountDetailsTableCounts = (walletAddress: HumanAddr) => {
refetchCodesCount,
refetchContractsAdminCount,
refetchContractsCount,
- refetchTxsCount,
refetchProposalsCount,
};
};
diff --git a/src/lib/model/contract.ts b/src/lib/model/contract.ts
index e213085b1..5d0432517 100644
--- a/src/lib/model/contract.ts
+++ b/src/lib/model/contract.ts
@@ -186,7 +186,13 @@ export const useContractDetailsTableCounts = (
const { data: migrationCount, refetch: refetchMigration } =
useMigrationHistoriesCountByContractAddress(contractAddress);
const { data: transactionsCount, refetch: refetchTransactions } =
- useTxsCountByAddress(contractAddress, "", DEFAULT_TX_FILTERS, undefined);
+ useTxsCountByAddress(
+ contractAddress,
+ undefined,
+ "",
+ DEFAULT_TX_FILTERS,
+ undefined
+ );
const { data: relatedProposalsCount, refetch: refetchRelatedProposals } =
useRelatedProposalsCountByContractAddress(contractAddress);
diff --git a/src/lib/pages/account-details/components/ErrorFetching.tsx b/src/lib/pages/account-details/components/ErrorFetching.tsx
new file mode 100644
index 000000000..cbca765f2
--- /dev/null
+++ b/src/lib/pages/account-details/components/ErrorFetching.tsx
@@ -0,0 +1,13 @@
+import { CustomIcon } from "lib/components/icon";
+
+export const ErrorFetching = () => (
+ <>
+
+ Error fetching data. Please try again later.
+ >
+);
diff --git a/src/lib/pages/account-details/components/asset/index.tsx b/src/lib/pages/account-details/components/asset/index.tsx
index 8858b5afb..a56e2105b 100644
--- a/src/lib/pages/account-details/components/asset/index.tsx
+++ b/src/lib/pages/account-details/components/asset/index.tsx
@@ -42,7 +42,7 @@ const AssetSectionContent = ({
{supportedAssets
.slice(0, onViewMore ? MaxAssetsShow : undefined)
.map((asset) => (
-
+
))}
) : (
@@ -64,7 +64,7 @@ export const AssetsSection = ({
if (isLoading) return ;
return (
-
+
{onViewMore && (
-
{unsupportedAssets && (
diff --git a/src/lib/pages/account-details/components/delegations/index.tsx b/src/lib/pages/account-details/components/delegations/index.tsx
index c93cafb86..e7aef9c9d 100644
--- a/src/lib/pages/account-details/components/delegations/index.tsx
+++ b/src/lib/pages/account-details/components/delegations/index.tsx
@@ -61,7 +61,7 @@ export const DelegationsSection = ({
if (isLoading) return ;
if (!stakingParams)
- return ;
+ return ;
const bondDenomLabel = getTokenLabel(stakingParams.bondDenom);
// TODO: support more than one Asset?
@@ -84,7 +84,7 @@ export const DelegationsSection = ({
const redelegationCount = redelegations?.length ?? 0;
return (
-
+
+ ) : (
+ "This account does not have any admin access for any contracts."
+ )
+ }
withBorder
/>
}
diff --git a/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx b/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx
index be3826ad4..9dba512b0 100644
--- a/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx
+++ b/src/lib/pages/account-details/components/tables/InstantiatedContractsTable.tsx
@@ -1,6 +1,7 @@
import { Box } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
+import { ErrorFetching } from "../ErrorFetching";
import { useInternalNavigate } from "lib/app-provider";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
@@ -77,8 +78,13 @@ export const InstantiatedContractsTable = ({
isLoading={isLoading}
emptyState={
+ ) : (
+ "This account did not instantiate any contracts before."
+ )
+ }
withBorder
/>
}
diff --git a/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx b/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx
index b6d81749b..af7aeb2bf 100644
--- a/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx
+++ b/src/lib/pages/account-details/components/tables/OpenedProposalsTable.tsx
@@ -1,6 +1,7 @@
import { Box } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
+import { ErrorFetching } from "../ErrorFetching";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
import { EmptyState } from "lib/components/state";
@@ -63,8 +64,13 @@ export const OpenedProposalsTable = ({
isLoading={isLoading}
emptyState={
+ ) : (
+ "This account did not open any proposals before."
+ )
+ }
withBorder
/>
}
diff --git a/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx b/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx
index dff6beef6..6d60648df 100644
--- a/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx
+++ b/src/lib/pages/account-details/components/tables/StoredCodesTable.tsx
@@ -1,6 +1,7 @@
import { Box } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
+import { ErrorFetching } from "../ErrorFetching";
import { useInternalNavigate } from "lib/app-provider";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
@@ -77,8 +78,13 @@ export const StoredCodesTable = ({
isLoading={isLoading}
emptyState={
+ ) : (
+ "This account did not stored any codes before."
+ )
+ }
withBorder
/>
}
diff --git a/src/lib/pages/account-details/components/tables/TxsTable.tsx b/src/lib/pages/account-details/components/tables/TxsTable.tsx
index 377358894..2acf6bf22 100644
--- a/src/lib/pages/account-details/components/tables/TxsTable.tsx
+++ b/src/lib/pages/account-details/components/tables/TxsTable.tsx
@@ -1,42 +1,63 @@
-// TODO - Refactor: move common component out of pasttx
-import { Box, Flex } from "@chakra-ui/react";
+import { Alert, AlertDescription, Box, Flex } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
-import { useState } from "react";
+import { useEffect, useState } from "react";
+import { ErrorFetching } from "../ErrorFetching";
+import { CustomIcon } from "lib/components/icon";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
+import type { EmptyStateProps } from "lib/components/state";
import { EmptyState } from "lib/components/state";
import { TableTitle, TransactionsTable, ViewMore } from "lib/components/table";
import { TxFilterSelection } from "lib/components/TxFilterSelection";
import { TxRelationSelection } from "lib/components/TxRelationSelection";
import { DEFAULT_TX_FILTERS } from "lib/data";
-import { useTxsByAddressPagination } from "lib/services/txService";
-import type { HumanAddr, Option, TxFilters } from "lib/types";
+import {
+ useTxsByAddressPagination,
+ useTxsCountByAddress,
+} from "lib/services/txService";
+import type { HumanAddr, Option, Transaction, TxFilters } from "lib/types";
interface TxsTableProps {
walletAddress: HumanAddr;
+ accountId?: Option;
scrollComponentId: string;
- totalData: Option;
- refetchCount: () => void;
onViewMore?: () => void;
}
-interface TxsTableBodyProps extends TxsTableProps {
- filters: TxFilters;
- filterSelected: string[];
- isSigner: Option;
-}
+const getEmptyStateProps = (
+ filterSelected: string[],
+ transactions: Option
+): EmptyStateProps => {
+ if (filterSelected.length) {
+ return { message: "No past transaction matches found with your input." };
+ }
+ if (!transactions) {
+ return {
+ message: ,
+ };
+ }
+ return {
+ message: "This account did not submit any transactions before.",
+ };
+};
-const TxsTableBody = ({
+export const TxsTable = ({
walletAddress,
+ accountId,
scrollComponentId,
- totalData,
- refetchCount,
onViewMore,
- filters,
- filterSelected,
- isSigner,
-}: TxsTableBodyProps) => {
+}: TxsTableProps) => {
+ const [isSigner, setIsSigner] = useState
handleTabChange(TabIndex.Txs)}
/>
{
diff --git a/src/lib/pages/block-details/components/BlockDetailsTop.tsx b/src/lib/pages/block-details/components/BlockDetailsTop.tsx
index f2e6df006..63c70261f 100644
--- a/src/lib/pages/block-details/components/BlockDetailsTop.tsx
+++ b/src/lib/pages/block-details/components/BlockDetailsTop.tsx
@@ -9,6 +9,7 @@ import {
import { useLCDEndpoint } from "lib/app-provider";
import { AppLink } from "lib/components/AppLink";
+import { CopyLink } from "lib/components/CopyLink";
import { DotSeparator } from "lib/components/DotSeparator";
import { CustomIcon } from "lib/components/icon";
import { openNewTab } from "lib/hooks";
@@ -34,7 +35,7 @@ export const BlockDetailsTop = ({ blockData }: BlockDetailsTopProps) => {
openNewTab(
`${lcdEndpoint}/cosmos/base/tendermint/v1beta1/blocks/${blockData.height}`
);
-
+ const disablePrevious = block <= 1;
return (
{
Block Hash:
-
- {blockData.hash.toUpperCase()}
-
+
@@ -73,12 +76,14 @@ export const BlockDetailsTop = ({ blockData }: BlockDetailsTopProps) => {
-
- }
- variant="ghost-gray"
- />
-
+ {!disablePrevious && (
+
+ }
+ variant="ghost-gray"
+ />
+
+ )}
}
diff --git a/src/lib/pages/block-details/components/BlockInfo.tsx b/src/lib/pages/block-details/components/BlockInfo.tsx
index 51569f194..856040996 100644
--- a/src/lib/pages/block-details/components/BlockInfo.tsx
+++ b/src/lib/pages/block-details/components/BlockInfo.tsx
@@ -2,7 +2,7 @@ import { Box, Flex, Heading } from "@chakra-ui/react";
import { LabelText } from "lib/components/LabelText";
import { ValidatorBadge } from "lib/components/ValidatorBadge";
-import type { BlockDetails } from "lib/types/block";
+import type { BlockDetails } from "lib/types";
import { formatInteger } from "lib/utils";
interface BlockInfoProps {
@@ -17,14 +17,14 @@ export const BlockInfo = ({ blockData }: BlockInfoProps) => {
{blockData.network}
-
-
-
{`${blockData.gasUsed ? formatInteger(blockData.gasUsed) : 0} / ${
blockData.gasLimit ? formatInteger(blockData.gasLimit) : 0
}`}
+
+
+
);
diff --git a/src/lib/pages/block-details/index.tsx b/src/lib/pages/block-details/index.tsx
index b012aef90..b6132185b 100644
--- a/src/lib/pages/block-details/index.tsx
+++ b/src/lib/pages/block-details/index.tsx
@@ -1,9 +1,11 @@
import { useRouter } from "next/router";
+import { useEffect } from "react";
import { BackButton } from "lib/components/button";
import { Loading } from "lib/components/Loading";
import PageContainer from "lib/components/PageContainer";
import { EmptyState } from "lib/components/state";
+import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { useBlockDetailsQuery } from "lib/services/blockService";
import { getFirstQueryParam } from "lib/utils";
@@ -20,6 +22,10 @@ const BlockDetail = () => {
Number(heightParam)
);
+ useEffect(() => {
+ if (router.isReady) AmpTrack(AmpEvent.TO_BLOCK_DETAIL);
+ }, [router.isReady]);
+
if (isLoading) return ;
return (
diff --git a/src/lib/pages/blocks/components/BlocksHeader.tsx b/src/lib/pages/blocks/components/BlocksHeader.tsx
index afd967de7..0e2aabcea 100644
--- a/src/lib/pages/blocks/components/BlocksHeader.tsx
+++ b/src/lib/pages/blocks/components/BlocksHeader.tsx
@@ -13,7 +13,11 @@ export const BlocksHeader = ({
scrollComponentId,
}: BlocksHeaderProps) => {
return (
-
+ div": { color: "text.dark" } }}
+ >
Block Height
Block Hash
Proposed by
diff --git a/src/lib/pages/blocks/components/BlocksRow.tsx b/src/lib/pages/blocks/components/BlocksRow.tsx
index 0e8133107..39a0ad498 100644
--- a/src/lib/pages/blocks/components/BlocksRow.tsx
+++ b/src/lib/pages/blocks/components/BlocksRow.tsx
@@ -28,7 +28,12 @@ export const BlocksRow = ({ templateColumns, blockData }: BlocksRowProps) => {
- {blockData.txCount}
+
+ {blockData.txCount}
+
diff --git a/src/lib/pages/blocks/index.tsx b/src/lib/pages/blocks/index.tsx
index 4ff10b50a..6ac44ad29 100644
--- a/src/lib/pages/blocks/index.tsx
+++ b/src/lib/pages/blocks/index.tsx
@@ -1,10 +1,18 @@
import { Heading, Text } from "@chakra-ui/react";
+import { useRouter } from "next/router";
+import { useEffect } from "react";
import PageContainer from "lib/components/PageContainer";
+import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { BlocksTable } from "./components/BlocksTable";
const BlocksPage = () => {
+ const router = useRouter();
+ useEffect(() => {
+ if (router.isReady) AmpTrack(AmpEvent.TO_BLOCKS);
+ }, [router.isReady]);
+
return (
diff --git a/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx b/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx
index 346ca1593..e0e79d3f6 100644
--- a/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx
+++ b/src/lib/pages/contract-details/components/tables/RelatedProposalsTable.tsx
@@ -64,7 +64,6 @@ export const RelatedProposalsTable = ({
}
/>
diff --git a/src/lib/pages/contract-details/components/tables/TxsTable.tsx b/src/lib/pages/contract-details/components/tables/TxsTable.tsx
index 060126c7d..59165c9a3 100644
--- a/src/lib/pages/contract-details/components/tables/TxsTable.tsx
+++ b/src/lib/pages/contract-details/components/tables/TxsTable.tsx
@@ -39,6 +39,7 @@ export const TxsTable = ({
const { data: transactions, isLoading } = useTxsByAddressPagination(
contractAddress,
+ undefined,
"",
DEFAULT_TX_FILTERS,
undefined,
@@ -67,7 +68,6 @@ export const TxsTable = ({
}
showRelations={false}
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 cee6f7b62..c96e85353 100644
--- a/src/lib/pages/contract-details/components/tables/migration/index.tsx
+++ b/src/lib/pages/contract-details/components/tables/migration/index.tsx
@@ -62,7 +62,6 @@ export const MigrationTable = ({
);
diff --git a/src/lib/pages/network-overview/index.tsx b/src/lib/pages/network-overview/index.tsx
index 0e7652c79..a39a1e79a 100644
--- a/src/lib/pages/network-overview/index.tsx
+++ b/src/lib/pages/network-overview/index.tsx
@@ -1,4 +1,6 @@
import { Box, Flex, Heading, Spinner, Text, Tooltip } from "@chakra-ui/react";
+import { useRouter } from "next/router";
+import { useEffect } from "react";
import { useInternalNavigate } from "lib/app-provider";
import { CustomIcon } from "lib/components/icon";
@@ -6,6 +8,7 @@ import PageContainer from "lib/components/PageContainer";
import { ViewMore } from "lib/components/table";
import { BlocksTable } from "lib/pages/blocks/components/BlocksTable";
import { TxsTable } from "lib/pages/txs/components/TxsTable";
+import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { useLatestBlockInfo } from "lib/services/blockService";
import { useTxsCount } from "lib/services/txService";
import { dateFromNow, formatUTC } from "lib/utils";
@@ -83,8 +86,13 @@ const CardInfo = ({
);
const NetworkOverview = () => {
+ const router = useRouter();
const navigate = useInternalNavigate();
+ useEffect(() => {
+ if (router.isReady) AmpTrack(AmpEvent.TO_NETWORK_OVERVIEW);
+ }, [router.isReady]);
+
const {
data: latestBlockInfo,
isLoading: isLoadingLatestBlockInfo,
@@ -142,7 +150,7 @@ const NetworkOverview = () => {
diff --git a/src/lib/pages/past-txs/index.tsx b/src/lib/pages/past-txs/index.tsx
index 1174623ac..aa8aebd73 100644
--- a/src/lib/pages/past-txs/index.tsx
+++ b/src/lib/pages/past-txs/index.tsx
@@ -20,6 +20,7 @@ import { TransactionsTableWithWallet } from "lib/components/table";
import { TxFilterSelection } from "lib/components/TxFilterSelection";
import { TxRelationSelection } from "lib/components/TxRelationSelection";
import { DEFAULT_TX_FILTERS } from "lib/data";
+import { useAccountId } from "lib/services/accountService";
import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import {
useTxsByAddressPagination,
@@ -50,8 +51,10 @@ const PastTxs = () => {
const pastTxsState = watch();
+ const { data: accountId } = useAccountId(address as HumanAddr);
const { data: countTxs = 0 } = useTxsCountByAddress(
- address as HumanAddr,
+ undefined,
+ accountId,
pastTxsState.search,
pastTxsState.filters,
pastTxsState.isSigner
@@ -74,7 +77,8 @@ const PastTxs = () => {
});
const { data: txs, isLoading } = useTxsByAddressPagination(
- address as HumanAddr,
+ undefined,
+ accountId,
pastTxsState.search,
pastTxsState.filters,
pastTxsState.isSigner,
@@ -82,7 +86,13 @@ const PastTxs = () => {
pageSize
);
+ const resetPagination = () => {
+ setPageSize(10);
+ setCurrentPage(1);
+ };
+
const setFilter = (filter: string, bool: boolean) => {
+ resetPagination();
setValue("filters", { ...pastTxsState.filters, [filter]: bool });
};
@@ -108,10 +118,6 @@ const PastTxs = () => {
);
}, [pastTxsState]);
- useEffect(() => {
- setCurrentPage(1);
- }, [pastTxsState.filters, pastTxsState.search, setCurrentPage]);
-
useEffect(() => {
if (router.isReady) AmpTrack(AmpEvent.TO_PAST_TXS);
}, [router.isReady]);
@@ -125,7 +131,10 @@ const PastTxs = () => {
setValue("search", e.target.value)}
+ onChange={(e) => {
+ setCurrentPage(1);
+ setValue("search", e.target.value);
+ }}
placeholder="Search with transaction hash or contract address"
h="full"
/>
@@ -136,7 +145,10 @@ const PastTxs = () => {
setValue("isSigner", value)}
+ setValue={(value) => {
+ resetPagination();
+ setValue("isSigner", value);
+ }}
w="165px"
/>
{
setValue,
reset,
formState: { errors: formErrors },
+ trigger,
} = useForm({
defaultValues,
mode: "all",
@@ -294,7 +295,9 @@ const ProposalToWhitelist = () => {
whitelisted: () =>
govParams?.uploadAccess.addresses?.includes(
addresses[idx].address
- ) && "This address is already included in whitelist",
+ )
+ ? "This address is already included in whitelist"
+ : undefined,
}}
error={formErrors.addresses?.[idx]?.address?.message}
helperAction={
@@ -305,6 +308,7 @@ const ProposalToWhitelist = () => {
`addresses.${idx}.address`,
walletAddress as Addr
);
+ trigger(`addresses.${idx}.address`);
}}
isDisable={
addresses.findIndex(
diff --git a/src/lib/pages/public-project/components/table/account/PublicProjectAccountRow.tsx b/src/lib/pages/public-project/components/table/account/PublicProjectAccountRow.tsx
new file mode 100644
index 000000000..f456829bd
--- /dev/null
+++ b/src/lib/pages/public-project/components/table/account/PublicProjectAccountRow.tsx
@@ -0,0 +1,68 @@
+import { Grid, Text } from "@chakra-ui/react";
+
+import type { NavigationArgs } from "lib/app-provider";
+import { useInternalNavigate } from "lib/app-provider";
+import { ExplorerLink } from "lib/components/ExplorerLink";
+import { TableRow } from "lib/components/table";
+import type { Account } from "lib/types";
+
+interface AccountTableRowProps {
+ accountInfo: Account;
+ templateColumns: string;
+}
+
+const getNavigationArgs = (accountInfo: Account): NavigationArgs => {
+ switch (accountInfo.type) {
+ case "account":
+ return {
+ pathname: "/account/[accountAddress]",
+ query: { accountAddress: accountInfo.address },
+ };
+ case "contract":
+ return {
+ pathname: "/contract/[accountAddress]",
+ query: { accountAddress: accountInfo.address },
+ };
+ default:
+ return {
+ pathname: "",
+ };
+ }
+};
+
+export const PublicProjectAccountRow = ({
+ accountInfo,
+ templateColumns,
+}: AccountTableRowProps) => {
+ const navigate = useInternalNavigate();
+ const goToDetail = () => {
+ navigate(getNavigationArgs(accountInfo));
+ };
+
+ return (
+
+
+
+
+ {accountInfo.name}
+
+
+ {accountInfo.description || "N/A"}
+
+
+
+ );
+};
diff --git a/src/lib/pages/public-project/components/table/account/PublicProjectAccountTable.tsx b/src/lib/pages/public-project/components/table/account/PublicProjectAccountTable.tsx
new file mode 100644
index 000000000..b273d88f1
--- /dev/null
+++ b/src/lib/pages/public-project/components/table/account/PublicProjectAccountTable.tsx
@@ -0,0 +1,79 @@
+import { TableContainer, Grid, Box } from "@chakra-ui/react";
+import { matchSorter } from "match-sorter";
+import { useMemo, useState } from "react";
+
+import { TextInput } from "lib/components/forms";
+import { EmptyState } from "lib/components/state";
+import { TableHeader, TableTitle, ViewMore } from "lib/components/table";
+import type { Account } from "lib/types";
+
+import { PublicProjectAccountRow } from "./PublicProjectAccountRow";
+
+interface PublicProjectAccountTableProps {
+ accounts: Account[];
+ onViewMore?: () => void;
+}
+
+const TEMPLATE_COLUMNS = "160px 320px minmax(250px, 1fr)";
+
+const AccountTableHeader = () => (
+
+ Address
+ Account Name
+ Description
+
+);
+
+export const PublicProjectAccountTable = ({
+ accounts = [],
+ onViewMore,
+}: PublicProjectAccountTableProps) => {
+ const [searchKeyword, setSearchKeyword] = useState("");
+ const filteredAccounts = useMemo(() => {
+ return onViewMore
+ ? accounts.slice(0, 5)
+ : matchSorter(accounts, searchKeyword, {
+ keys: ["name", "address", "description"],
+ threshold: matchSorter.rankings.CONTAINS,
+ });
+ }, [accounts, onViewMore, searchKeyword]);
+
+ return (
+
+
+ {!onViewMore && (
+
+ )}
+ {!filteredAccounts.length ? (
+
+ ) : (
+ <>
+
+
+ {filteredAccounts.map((account) => (
+
+ ))}
+
+ {accounts.length > 5 && onViewMore && (
+
+ )}
+ >
+ )}
+
+ );
+};
diff --git a/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx b/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx
index e8f81b170..31f96a4d4 100644
--- a/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx
+++ b/src/lib/pages/public-project/components/table/code/PublicProjectCodeTable.tsx
@@ -90,7 +90,7 @@ export const PublicProjectCodeTable = observer(
/>
) : (
<>
-
+
{publicCodes.map((code) => (
))}
- {onViewMore && }
+ {codes.length > 5 && onViewMore && (
+
+ )}
>
)}
diff --git a/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx b/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx
index 8a2cb97cb..6ae578a71 100644
--- a/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx
+++ b/src/lib/pages/public-project/components/table/contract/PublicProjectContractTable.tsx
@@ -80,7 +80,7 @@ export const PublicProjectContractTable = observer(
/>
) : (
<>
-
+
{publicContracts.map((contract) => (
))}
- {onViewMore && }
+ {contracts.length > 5 && onViewMore && (
+
+ )}
>
)}
diff --git a/src/lib/pages/public-project/data.ts b/src/lib/pages/public-project/data.ts
index f394bfe3d..a8ae5ed0d 100644
--- a/src/lib/pages/public-project/data.ts
+++ b/src/lib/pages/public-project/data.ts
@@ -6,12 +6,14 @@ import type {
PublicContract,
PublicDetail,
Option,
+ Account,
} from "lib/types";
import { getFirstQueryParam } from "lib/utils";
interface PublicDataState {
publicCodes: PublicCode[];
publicContracts: PublicContract[];
+ publicAccounts: Account[];
projectDetail: Option;
slug: string;
isLoading: boolean;
@@ -26,6 +28,7 @@ export const usePublicData = (): PublicDataState => {
return {
publicCodes: projectInfo?.codes || [],
publicContracts: projectInfo?.contracts || [],
+ publicAccounts: projectInfo?.accounts || [],
projectDetail: projectInfo?.details,
slug: projectSlug,
isLoading,
diff --git a/src/lib/pages/public-project/slug.tsx b/src/lib/pages/public-project/slug.tsx
index 95a09e5c3..6c967f85d 100644
--- a/src/lib/pages/public-project/slug.tsx
+++ b/src/lib/pages/public-project/slug.tsx
@@ -1,5 +1,4 @@
import { Tabs, TabList, TabPanels, TabPanel } from "@chakra-ui/react";
-import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
@@ -10,6 +9,7 @@ import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { scrollToTop } from "lib/utils";
import { DetailHeader } from "./components/DetailHeader";
+import { PublicProjectAccountTable } from "./components/table/account/PublicProjectAccountTable";
import { PublicProjectCodeTable } from "./components/table/code/PublicProjectCodeTable";
import { PublicProjectContractTable } from "./components/table/contract/PublicProjectContractTable";
import { usePublicData } from "./data";
@@ -18,13 +18,20 @@ enum TabIndex {
Overview,
Codes,
Contracts,
+ Accounts,
}
-export const ProjectDetail = observer(() => {
+export const ProjectDetail = () => {
const router = useRouter();
const [tabIndex, setTabIndex] = useState(TabIndex.Overview);
- const { publicCodes, publicContracts, projectDetail, slug, isLoading } =
- usePublicData();
+ const {
+ publicCodes,
+ publicContracts,
+ publicAccounts,
+ projectDetail,
+ slug,
+ isLoading,
+ } = usePublicData();
useEffect(() => {
if (router.isReady) AmpTrack(AmpEvent.TO_PROJECT_DETAIL);
@@ -40,9 +47,13 @@ export const ProjectDetail = observer(() => {
-
+
setTabIndex(TabIndex.Overview)}
>
Overview
@@ -61,6 +72,13 @@ export const ProjectDetail = observer(() => {
>
Contracts
+ setTabIndex(TabIndex.Accounts)}
+ >
+ Accounts
+
@@ -73,6 +91,10 @@ export const ProjectDetail = observer(() => {
contracts={publicContracts}
onViewMore={() => handleOnViewMore(TabIndex.Contracts)}
/>
+ handleOnViewMore(TabIndex.Accounts)}
+ />
@@ -80,8 +102,11 @@ export const ProjectDetail = observer(() => {
+
+
+
);
-});
+};
diff --git a/src/lib/pages/txs/index.tsx b/src/lib/pages/txs/index.tsx
index 25ab85b41..af59b1aea 100644
--- a/src/lib/pages/txs/index.tsx
+++ b/src/lib/pages/txs/index.tsx
@@ -1,19 +1,29 @@
import { Heading, Text } from "@chakra-ui/react";
+import { useRouter } from "next/router";
+import { useEffect } from "react";
import PageContainer from "lib/components/PageContainer";
+import { AmpEvent, AmpTrack } from "lib/services/amplitude";
import { TxsTable } from "./components/TxsTable";
-const Txs = () => (
-
-
- Transactions
-
-
- This page displays all transactions in this network sorted by recency
-
-
-
-);
+const Txs = () => {
+ const router = useRouter();
+ useEffect(() => {
+ if (router.isReady) AmpTrack(AmpEvent.TO_TXS);
+ }, [router.isReady]);
+
+ return (
+
+
+ Transactions
+
+
+ This page displays all transactions in this network sorted by recency
+
+
+
+ );
+};
export default Txs;
diff --git a/src/lib/query-utils/index.ts b/src/lib/query-utils/index.ts
new file mode 100644
index 000000000..76e4e39d1
--- /dev/null
+++ b/src/lib/query-utils/index.ts
@@ -0,0 +1,17 @@
+export const createQueryFnWithTimeout =
+ (queryFn: () => Promise, ms: number = 6 * 1000) =>
+ () =>
+ Promise.race([
+ queryFn(),
+ new Promise((_, reject) => {
+ setTimeout(
+ () =>
+ reject(
+ new Error(
+ `Failed to receive query response in ${ms} milliseconds`
+ )
+ ),
+ ms
+ );
+ }),
+ ]);
diff --git a/src/lib/query/account.ts b/src/lib/query/account.ts
new file mode 100644
index 000000000..1d945ff89
--- /dev/null
+++ b/src/lib/query/account.ts
@@ -0,0 +1,9 @@
+import { graphql } from "lib/gql";
+
+export const getAccountIdByAddressQueryDocument = graphql(`
+ query getAccountIdByAddressQueryDocument($address: String!) {
+ accounts_by_pk(address: $address) {
+ id
+ }
+ }
+`);
diff --git a/src/lib/query/index.ts b/src/lib/query/index.ts
index d919d9a2b..887469776 100644
--- a/src/lib/query/index.ts
+++ b/src/lib/query/index.ts
@@ -4,3 +4,4 @@ export * from "./contract";
export * from "./pool";
export * from "./proposal";
export * from "./tx";
+export * from "./account";
diff --git a/src/lib/services/accountService.ts b/src/lib/services/accountService.ts
index 432dcf0d8..11790446e 100644
--- a/src/lib/services/accountService.ts
+++ b/src/lib/services/accountService.ts
@@ -2,7 +2,9 @@ import { useWallet } from "@cosmos-kit/react";
import type { UseQueryResult } from "@tanstack/react-query";
import { useQuery } from "@tanstack/react-query";
-import type { Addr, Balance } from "lib/types";
+import { useCelatoneApp } from "lib/app-provider";
+import { getAccountIdByAddressQueryDocument } from "lib/query";
+import type { Addr, Balance, Option } from "lib/types";
import { getAccountBalanceInfo } from "./account";
@@ -24,6 +26,28 @@ export const useAccountBalances = (
currentChainRecord?.name,
currentChainRecord?.chain.chain_id
),
- { enabled: !!currentChainRecord || !!walletAddress }
+ {
+ enabled: !!currentChainRecord || !!walletAddress,
+ retry: 1,
+ refetchOnWindowFocus: false,
+ }
);
};
+
+export const useAccountId = (
+ walletAddress: Option
+): UseQueryResult> => {
+ const { indexerGraphClient } = useCelatoneApp();
+ const queryFn = () => {
+ if (!walletAddress)
+ throw new Error("Error fetching account id: failed to retrieve address.");
+ return indexerGraphClient
+ .request(getAccountIdByAddressQueryDocument, { address: walletAddress })
+ .then>(({ accounts_by_pk }) => accounts_by_pk?.id);
+ };
+ return useQuery(["account_id", indexerGraphClient, walletAddress], queryFn, {
+ enabled: Boolean(walletAddress),
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
+};
diff --git a/src/lib/services/amplitude.tsx b/src/lib/services/amplitude.tsx
index bebd8aff2..abb845856 100644
--- a/src/lib/services/amplitude.tsx
+++ b/src/lib/services/amplitude.tsx
@@ -27,6 +27,10 @@ export enum AmpEvent {
PUBLIC_REMOVE = "Public Project Remove",
// NAVIGATE
TO_OVERVIEW = "To Overview",
+ TO_NETWORK_OVERVIEW = "To Network Overview",
+ TO_BLOCKS = "To Blocks",
+ TO_BLOCK_DETAIL = "To Block Detail",
+ TO_TXS = "To Txs",
TO_PAST_TXS = "To Past Txs",
TO_DEPLOY = "To Deploy",
TO_UPLOAD = "To Upload",
diff --git a/src/lib/services/assetService.ts b/src/lib/services/assetService.ts
index b425a3194..9511a0c69 100644
--- a/src/lib/services/assetService.ts
+++ b/src/lib/services/assetService.ts
@@ -24,7 +24,7 @@ export const useAssetInfos = (): {
currentChainRecord?.name,
currentChainRecord?.chain.chain_id
),
- { enabled: !!currentChainRecord }
+ { enabled: !!currentChainRecord, retry: 1, refetchOnWindowFocus: false }
);
return {
diff --git a/src/lib/services/codeService.ts b/src/lib/services/codeService.ts
index 83bffb74f..928a06010 100644
--- a/src/lib/services/codeService.ts
+++ b/src/lib/services/codeService.ts
@@ -12,6 +12,7 @@ import {
getCodeListCountByWalletAddress,
getCodeListQueryDocument,
} from "lib/query";
+import { createQueryFnWithTimeout } from "lib/query-utils";
import type {
CodeInfo,
CodeData,
@@ -200,8 +201,8 @@ export const useCodeListByWalletAddressPagination = (
pageSize,
walletAddress,
],
- queryFn,
- { enabled: !!walletAddress }
+ createQueryFnWithTimeout(queryFn),
+ { enabled: !!walletAddress, retry: 1, refetchOnWindowFocus: false }
);
};
diff --git a/src/lib/services/contractService.ts b/src/lib/services/contractService.ts
index 3c5e361c8..8dafcbaa9 100644
--- a/src/lib/services/contractService.ts
+++ b/src/lib/services/contractService.ts
@@ -17,6 +17,7 @@ import {
getMigrationHistoriesByContractAddressPagination,
getMigrationHistoriesCountByContractAddress,
} from "lib/query";
+import { createQueryFnWithTimeout } from "lib/query-utils";
import type { ContractLocalInfo } from "lib/stores/contract";
import type {
ContractAddr,
@@ -371,8 +372,8 @@ export const useContractListByWalletAddressPagination = (
pageSize,
walletAddress,
],
- queryFn,
- { enabled: !!walletAddress }
+ createQueryFnWithTimeout(queryFn),
+ { enabled: !!walletAddress, retry: 1, refetchOnWindowFocus: false }
);
};
@@ -417,8 +418,8 @@ export const useContractListByAdminPagination = (
pageSize,
walletAddress,
],
- queryFn,
- { enabled: !!walletAddress }
+ createQueryFnWithTimeout(queryFn),
+ { enabled: !!walletAddress, retry: 1, refetchOnWindowFocus: false }
);
};
@@ -439,7 +440,7 @@ export const useContractListCountByAdmin = (
return useQuery(
["contract_list_count_by_admin", walletAddress, indexerGraphClient],
- queryFn,
+ createQueryFnWithTimeout(queryFn),
{
keepPreviousData: true,
enabled: !!walletAddress,
diff --git a/src/lib/services/delegationService.ts b/src/lib/services/delegationService.ts
index 82dd523c0..37a920abc 100644
--- a/src/lib/services/delegationService.ts
+++ b/src/lib/services/delegationService.ts
@@ -30,7 +30,10 @@ export const useStakingParams = (): UseQueryResult => {
[endpoint]
);
- return useQuery(["query", "staking_params", endpoint], queryFn);
+ return useQuery(["query", "staking_params", endpoint], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
export const useDelegations = (
@@ -43,7 +46,10 @@ export const useDelegations = (
[address, endpoint]
);
- return useQuery(["query", "delegations", endpoint, address], queryFn);
+ return useQuery(["query", "delegations", endpoint, address], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
export const useUnbondings = (
@@ -56,7 +62,10 @@ export const useUnbondings = (
[address, endpoint]
);
- return useQuery(["query", "unbondings", endpoint, address], queryFn);
+ return useQuery(["query", "unbondings", endpoint, address], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
export const useDelegationRewards = (
@@ -69,7 +78,10 @@ export const useDelegationRewards = (
[address, endpoint]
);
- return useQuery(["query", "delegation_rewards", endpoint, address], queryFn);
+ return useQuery(["query", "delegation_rewards", endpoint, address], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
export const useRedelegations = (
@@ -82,7 +94,10 @@ export const useRedelegations = (
[address, endpoint]
);
- return useQuery(["query", "redelegations", endpoint, address], queryFn);
+ return useQuery(["query", "redelegations", endpoint, address], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
export const useCommission = (
@@ -95,5 +110,8 @@ export const useCommission = (
[address, endpoint]
);
- return useQuery(["query", "commission", endpoint, address], queryFn);
+ return useQuery(["query", "commission", endpoint, address], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
diff --git a/src/lib/services/expression/txExpression.ts b/src/lib/services/expression/txExpression.ts
index d209f32a9..19b1155a6 100644
--- a/src/lib/services/expression/txExpression.ts
+++ b/src/lib/services/expression/txExpression.ts
@@ -34,23 +34,47 @@ const generateSearch = (search: string) =>
]
: [{}];
-export const useTxExpression = (
- address: Option,
- search: string,
- filters: TxFilters,
- isSigner: Option
-) =>
- useMemo(
- () => ({
- account: { address: address ? { _eq: address } : {} },
- is_signer: isSigner === undefined ? {} : { _eq: isSigner },
- transaction: {
- ...generateActionsFilter(filters),
- _or: generateSearch(search.toLocaleLowerCase()),
- },
- }),
- [address, filters, isSigner, search]
- );
+export const useTxExpression = ({
+ address,
+ accountId,
+ search,
+ filters,
+ isSigner,
+}: {
+ address?: Option;
+ accountId?: Option;
+ search: string;
+ filters: TxFilters;
+ isSigner: Option;
+}) =>
+ useMemo(() => {
+ const hasFilter = Object.values(filters).some((filter: boolean) => filter);
+ const accountIdExp = accountId ? { account_id: { _eq: accountId } } : {};
+ const addressExp = address
+ ? { account: { address: { _eq: address } } }
+ : {};
+ const applyAccountExp = Object.keys(accountIdExp).length
+ ? accountIdExp
+ : addressExp;
+ const isSignerExp =
+ isSigner === undefined ? {} : { is_signer: { _eq: isSigner } };
+ const filterExp =
+ hasFilter || search
+ ? {
+ transaction: {
+ ...(hasFilter ? generateActionsFilter(filters) : {}),
+ ...(search
+ ? { _or: generateSearch(search.toLocaleLowerCase()) }
+ : {}),
+ },
+ }
+ : {};
+ return {
+ ...applyAccountExp,
+ ...isSignerExp,
+ ...filterExp,
+ };
+ }, [address, accountId, filters, isSigner, search]);
export const usePoolTxExpression = (
poolId: Option,
diff --git a/src/lib/services/proposalService.ts b/src/lib/services/proposalService.ts
index 77bf395ed..6e523b87d 100644
--- a/src/lib/services/proposalService.ts
+++ b/src/lib/services/proposalService.ts
@@ -12,6 +12,7 @@ import {
getRelatedProposalsByContractAddressPagination,
getRelatedProposalsCountByContractAddress,
} from "lib/query";
+import { createQueryFnWithTimeout } from "lib/query-utils";
import type {
ContractAddr,
HumanAddr,
@@ -146,9 +147,11 @@ export const useProposalsByWalletAddressPagination = (
offset,
pageSize,
],
- queryFn,
+ createQueryFnWithTimeout(queryFn),
{
enabled: !!walletAddress,
+ retry: 1,
+ refetchOnWindowFocus: false,
}
);
};
diff --git a/src/lib/services/publicProjectService.ts b/src/lib/services/publicProjectService.ts
index 11df596c4..1c9c7aa10 100644
--- a/src/lib/services/publicProjectService.ts
+++ b/src/lib/services/publicProjectService.ts
@@ -153,3 +153,34 @@ export const usePublicProjectByCodeId = (
}
);
};
+
+export const usePublicProjectByAccountAddress = (
+ accountAddress: Option
+): UseQueryResult => {
+ const { currentChainRecord } = useWallet();
+ const queryFn = useCallback(async () => {
+ if (!accountAddress)
+ throw new Error(
+ "Wallet address not found (usePublicProjectByAccountAddress)"
+ );
+ if (!currentChainRecord)
+ throw new Error("No chain selected (usePublicProjectByAccountAddress)");
+ return axios
+ .get(
+ `${CELATONE_API_ENDPOINT}/accounts/${getChainApiPath(
+ currentChainRecord.chain.chain_name
+ )}/${currentChainRecord.chain.chain_id}/${accountAddress}`
+ )
+ .then(({ data: projectInfo }) => projectInfo);
+ }, [accountAddress, currentChainRecord]);
+ return useQuery(
+ ["public_project_by_account_address", accountAddress, currentChainRecord],
+ queryFn,
+ {
+ keepPreviousData: true,
+ enabled: !!accountAddress,
+ retry: false,
+ refetchOnWindowFocus: false,
+ }
+ );
+};
diff --git a/src/lib/services/txService.ts b/src/lib/services/txService.ts
index 5fbb04a92..82fd31469 100644
--- a/src/lib/services/txService.ts
+++ b/src/lib/services/txService.ts
@@ -17,6 +17,7 @@ import {
getBlockTransactionCountByHeightQueryDocument,
getBlockTransactionsByHeightQueryDocument,
} from "lib/query";
+import { createQueryFnWithTimeout } from "lib/query-utils";
import type {
Addr,
Option,
@@ -71,6 +72,7 @@ export const useTxData = (txHash: Option): UseQueryResult => {
export const useTxsByAddressPagination = (
address: Option,
+ accountId: Option,
search: string,
filters: TxFilters,
isSigner: Option,
@@ -78,7 +80,13 @@ export const useTxsByAddressPagination = (
pageSize: number
): UseQueryResult => {
const { indexerGraphClient } = useCelatoneApp();
- const expression = useTxExpression(address, search, filters, isSigner);
+ const expression = useTxExpression({
+ address,
+ accountId,
+ search,
+ filters,
+ isSigner,
+ });
const queryFn = useCallback(
async () =>
@@ -89,9 +97,11 @@ export const useTxsByAddressPagination = (
pageSize,
})
.then(({ account_transactions }) =>
- account_transactions.map((transaction) => ({
+ account_transactions.map((transaction) => ({
hash: parseTxHash(transaction.transaction.hash),
- messages: snakeToCamel(transaction.transaction.messages),
+ messages: snakeToCamel(
+ transaction.transaction.messages
+ ) as Message[],
sender: transaction.transaction.account.address as Addr,
isSigner: transaction.is_signer,
height: transaction.block.height,
@@ -127,11 +137,11 @@ export const useTxsByAddressPagination = (
),
[expression, indexerGraphClient, offset, pageSize]
);
-
return useQuery(
[
"transactions_by_address_pagination",
address,
+ accountId,
search,
filters,
isSigner,
@@ -139,21 +149,30 @@ export const useTxsByAddressPagination = (
pageSize,
indexerGraphClient,
],
- queryFn,
+ createQueryFnWithTimeout(queryFn),
{
- enabled: !!address,
+ enabled: !!address || !!accountId,
+ retry: 1,
+ refetchOnWindowFocus: false,
}
);
};
export const useTxsCountByAddress = (
address: Option,
+ accountId: Option,
search: string,
filters: TxFilters,
isSigner: Option
): UseQueryResult> => {
const { indexerGraphClient } = useCelatoneApp();
- const expression = useTxExpression(address, search, filters, isSigner);
+ const expression = useTxExpression({
+ address,
+ accountId,
+ search,
+ filters,
+ isSigner,
+ });
const queryFn = useCallback(
async () =>
@@ -179,7 +198,9 @@ export const useTxsCountByAddress = (
],
queryFn,
{
- enabled: !!address,
+ enabled: !!address || !!accountId,
+ retry: 0,
+ refetchOnWindowFocus: false,
}
);
};
diff --git a/src/lib/services/validatorService.ts b/src/lib/services/validatorService.ts
index 6fd7f67df..f0d9ac20f 100644
--- a/src/lib/services/validatorService.ts
+++ b/src/lib/services/validatorService.ts
@@ -14,5 +14,8 @@ export const useValidators = (): UseQueryResult<
const queryFn = useCallback(async () => getValidators(endpoint), [endpoint]);
- return useQuery(["query", "validators", endpoint], queryFn);
+ return useQuery(["query", "validators", endpoint], queryFn, {
+ retry: 1,
+ refetchOnWindowFocus: false,
+ });
};
diff --git a/src/lib/styles/theme/components/button.ts b/src/lib/styles/theme/components/button.ts
index 187a5544b..ef535b997 100644
--- a/src/lib/styles/theme/components/button.ts
+++ b/src/lib/styles/theme/components/button.ts
@@ -173,9 +173,9 @@ export const Button: ComponentStyleConfig = {
color: "pebble.400",
},
disabled: {
- color: "pebble.500",
+ color: "pebble.600",
},
- hoverBg: pebble700,
+ hoverBg: "pebble.800",
activeBg: "transparent",
}),
"ghost-error": generateStyle({
diff --git a/src/lib/types/projects.ts b/src/lib/types/projects.ts
index f5d68396b..80585b373 100644
--- a/src/lib/types/projects.ts
+++ b/src/lib/types/projects.ts
@@ -13,6 +13,7 @@ export interface Account {
description: string;
name: string;
slug: string;
+ type: string;
}
export interface RawPublicCode {
diff --git a/src/lib/utils/formatter/index.ts b/src/lib/utils/formatter/index.ts
index 39c98fc82..9bce96c57 100644
--- a/src/lib/utils/formatter/index.ts
+++ b/src/lib/utils/formatter/index.ts
@@ -8,3 +8,4 @@ export * from "./formatBalanceWithDenom";
export * from "./formatPercentValue";
export * from "./tokenType";
export * from "./token";
+export * from "./text";
diff --git a/src/lib/utils/formatter/text.ts b/src/lib/utils/formatter/text.ts
new file mode 100644
index 000000000..87d32ff52
--- /dev/null
+++ b/src/lib/utils/formatter/text.ts
@@ -0,0 +1,2 @@
+export const removeSpecialChars = (text: string) =>
+ text.replace(/[^a-zA-Z0-9]/g, "");