Skip to content

Commit

Permalink
[account] Fix refreshes, and reduce excess API queries (#985)
Browse files Browse the repository at this point in the history
This removes repeated account resources queries.  It removes the
constant refresh on deleted resources, adds object ownership info
easily accessible as well, and should handle mixed account / object.

Resolves #957
  • Loading branch information
gregnazario authored Jan 13, 2025
1 parent 3cd356f commit e0928f7
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 93 deletions.
89 changes: 54 additions & 35 deletions src/pages/Account/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import AccountTitle from "./Title";
import BalanceCard from "./BalanceCard";
import PageHeader from "../layout/PageHeader";
import {useGetIsGraphqlClientSupported} from "../../api/hooks/useGraphqlClient";
import {useGetAccount} from "../../api/hooks/useGetAccount";
import LoadingModal from "../../components/LoadingModal";
import Error from "./Error";
import {AptosNamesBanner} from "./Components/AptosNamesBanner";
import {useGlobalState} from "../../global-config/GlobalConfig";
import {Network} from "aptos";
import {Network, Types} from "aptos";
import {useGetAccountResources} from "../../api/hooks/useGetAccountResources";
import {AccountAddress} from "@aptos-labs/ts-sdk";
import {useNavigate} from "../../routing";
Expand All @@ -36,8 +35,14 @@ const OBJECT_VALUES_FULL: TabValue[] = [
"tokens",
"resources",
"modules",
"info",
];
const OBJECT_TAB_VALUES: TabValue[] = [
"transactions",
"resources",
"modules",
"info",
];
const OBJECT_TAB_VALUES: TabValue[] = ["transactions", "resources", "modules"];

type AccountPageProps = {
isObject?: boolean;
Expand All @@ -50,7 +55,9 @@ export function accountPagePath(isObject: boolean) {
return "account";
}

export default function AccountPage({isObject = false}: AccountPageProps) {
export default function AccountPage({
isObject: alreadyIsObject,
}: AccountPageProps) {
const navigate = useNavigate();
const isGraphqlClientSupported = useGetIsGraphqlClientSupported();
const maybeAddress = useParams().address;
Expand All @@ -70,39 +77,49 @@ export default function AccountPage({isObject = false}: AccountPageProps) {
}

const {
data: objectData,
error: objectError,
isLoading: objectIsLoading,
data: resourceData,
error: resourceError,
isLoading: resourcesIsLoading,
} = useGetAccountResources(address, {retry: false});
const {
data: accountData,
error: accountError,
isLoading: accountIsLoading,
} = useGetAccount(address, {retry: false});

const isDeleted = !objectData?.find((r) => r.type === objectCoreResource);
const accountData = resourceData?.find(
(r) => r.type === "0x1::account::Account",
)?.data as Types.AccountData | undefined;
const objectData = resourceData?.find((r) => r.type === objectCoreResource);
const tokenData = resourceData?.find((r) => r.type === "0x4::token::Token");
const isAccount = !!accountData;
const isObject = !!objectData;
const isDeleted = !isObject;
const isToken = !!tokenData;

const isLoading = objectIsLoading || accountIsLoading;
const data = isObject ? objectData : accountData;
let error: ResponseError | null;
const isLoading = resourcesIsLoading;
let error: ResponseError | null = null;
if (addressError) {
error = addressError;
} else if (isObject) {
error = objectError;
} else {
error = accountError ? accountError : objectError;
} else if (resourceError) {
error = resourceError;
}

useEffect(() => {
// If we are on the account page, we might be loading an object. This
// handler will redirect to the object page if no account exists but an
// object does.
if (!isObject && !isLoading) {
if (objectData && !accountData) {
if (!isLoading) {
// TODO: Handle where it's both an object and an account
if (!alreadyIsObject && isObject && !isAccount) {
navigate(`/object/${address}`, {replace: true});
}
}
}, [address, isObject, isLoading, accountData, objectData, navigate]);
}, [
address,
alreadyIsObject,
isObject,
isLoading,
accountData,
resourceData,
navigate,
isAccount,
]);

const [state] = useGlobalState();

Expand All @@ -115,6 +132,17 @@ export default function AccountPage({isObject = false}: AccountPageProps) {
tabValues = isGraphqlClientSupported ? TAB_VALUES_FULL : TAB_VALUES;
}

const accountTabs = (
<AccountTabs
address={address}
accountData={accountData}
objectData={objectData}
resourceData={resourceData}
tabValues={tabValues}
isObject={isObject}
/>
);

return (
<Grid2 container spacing={1}>
<LoadingModal open={isLoading} />
Expand All @@ -126,6 +154,7 @@ export default function AccountPage({isObject = false}: AccountPageProps) {
address={address}
isObject={isObject}
isDeleted={isDeleted}
isToken={isToken}
/>
</Grid2>
<Grid2 size={{xs: 12, md: 4, lg: 3}} marginTop={{md: 0, xs: 2}}>
Expand All @@ -137,21 +166,11 @@ export default function AccountPage({isObject = false}: AccountPageProps) {
<Grid2 size={{xs: 12, md: 12, lg: 12}} marginTop={4}>
{error ? (
<>
<AccountTabs
address={address}
accountData={data}
tabValues={tabValues}
isObject={isObject}
/>
{accountTabs}
<Error address={address} error={error} />
</>
) : (
<AccountTabs
address={address}
accountData={data}
tabValues={tabValues}
isObject={isObject}
/>
<>{accountTabs}</>
)}
</Grid2>
</Grid2>
Expand Down
16 changes: 14 additions & 2 deletions src/pages/Account/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,29 +74,37 @@ function getTabIcon(value: TabValue): JSX.Element {
type TabPanelProps = {
value: TabValue;
address: string;
accountData: Types.AccountData | Types.MoveResource[] | undefined;
accountData: Types.AccountData | undefined;
objectData: Types.MoveResource | undefined;
resourceData: Types.MoveResource[] | undefined;
isObject: boolean;
};

function TabPanel({
value,
address,
accountData,
objectData,
resourceData,
isObject,
}: TabPanelProps): JSX.Element {
const TabComponent = TabComponents[value];
return (
<TabComponent
address={address}
accountData={accountData}
objectData={objectData}
resourceData={resourceData}
isObject={isObject}
/>
);
}

type AccountTabsProps = {
address: string;
accountData: Types.AccountData | Types.MoveResource[] | undefined;
accountData: Types.AccountData | undefined;
objectData: Types.MoveResource | undefined;
resourceData: Types.MoveResource[] | undefined;
tabValues?: TabValue[];
isObject?: boolean;
};
Expand All @@ -105,6 +113,8 @@ type AccountTabsProps = {
export default function AccountTabs({
address,
accountData,
objectData,
resourceData,
isObject = false,
tabValues = TAB_VALUES,
}: AccountTabsProps): JSX.Element {
Expand Down Expand Up @@ -146,6 +156,8 @@ export default function AccountTabs({
value={effectiveTab}
address={address}
accountData={accountData}
objectData={objectData}
resourceData={resourceData}
isObject={isObject}
/>
</Box>
Expand Down
2 changes: 0 additions & 2 deletions src/pages/Account/Tabs/CoinsTab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import EmptyTabContent from "../../../components/IndividualPageContent/EmptyTabContent";
import {Types} from "aptos";
import {CoinDescriptionPlusAmount, CoinsTable} from "../Components/CoinsTable";
import {
CoinDescription,
Expand All @@ -12,7 +11,6 @@ import {coinOrderIndex} from "../../utils";

type TokenTabsProps = {
address: string;
accountData: Types.AccountData | Types.MoveResource[] | undefined;
};

export default function CoinsTab({address}: TokenTabsProps) {
Expand Down
99 changes: 69 additions & 30 deletions src/pages/Account/Tabs/InfoTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,84 @@ import {tryStandardizeAddress} from "../../../utils";

type InfoTabProps = {
address: string;
accountData: Types.AccountData | Types.MoveResource[] | undefined;
accountData: Types.AccountData | undefined;
objectData: Types.MoveResource | undefined;
};

export default function InfoTab({address, accountData}: InfoTabProps) {
if (!accountData || Array.isArray(accountData)) {
export default function InfoTab({
address,
accountData,
objectData,
}: InfoTabProps) {
if (!accountData && !objectData) {
return <EmptyTabContent />;
}

const keyRotated =
tryStandardizeAddress(address) !==
tryStandardizeAddress(accountData.authentication_key);
let accountInfo = null;
if (accountData) {
const keyRotated =
tryStandardizeAddress(address) !==
tryStandardizeAddress(accountData.authentication_key);

return (
<Box marginBottom={3}>
<ContentBox>
<ContentRow
title={"Sequence Number:"}
value={accountData.sequence_number}
tooltip={getLearnMoreTooltip("sequence_number")}
/>
{keyRotated ? (
accountInfo = (
<Box marginBottom={3}>
<ContentBox>
<ContentRow
title={"Authentication Key:"}
value={
<>
{`${accountData.authentication_key} `}
<span style={{marginLeft: 8, color: grey[450]}}>(rotated)</span>
</>
}
tooltip={getLearnMoreTooltip("authentication_key")}
title={"Sequence Number:"}
value={accountData.sequence_number}
tooltip={getLearnMoreTooltip("sequence_number")}
/>
{keyRotated ? (
<ContentRow
title={"Authentication Key:"}
value={
<>
{`${accountData.authentication_key} `}
<span style={{marginLeft: 8, color: grey[450]}}>
(rotated)
</span>
</>
}
tooltip={getLearnMoreTooltip("authentication_key")}
/>
) : (
<ContentRow
title={"Authentication Key:"}
value={accountData.authentication_key}
tooltip={getLearnMoreTooltip("authentication_key")}
/>
)}
</ContentBox>
</Box>
);
}

let objectInfo = null;
if (objectData) {
objectInfo = (
<Box marginBottom={3}>
<ContentBox>
<ContentRow
title={"Owner:"}
value={(objectData.data as any).owner}
tooltip={getLearnMoreTooltip("owner")}
/>
) : (
<ContentRow
title={"Authentication Key:"}
value={accountData.authentication_key}
tooltip={getLearnMoreTooltip("authentication_key")}
title={"Transferrable:"}
value={
(objectData.data as any).allow_ungated_transfer ? "Yes" : "No"
}
tooltip={getLearnMoreTooltip("allow_ungated_transfer")}
/>
)}
</ContentBox>
</Box>
</ContentBox>
</Box>
);
}

return (
<>
{accountInfo}
{objectInfo}
</>
);
}
25 changes: 6 additions & 19 deletions src/pages/Account/Tabs/ResourcesTab.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import {Types} from "aptos";
import React from "react";
import Error from "../Error";
import {useGetAccountResources} from "../../../api/hooks/useGetAccountResources";
import EmptyTabContent from "../../../components/IndividualPageContent/EmptyTabContent";
import useExpandedList from "../../../components/hooks/useExpandedList";
import CollapsibleCards from "../../../components/IndividualPageContent/CollapsibleCards";
import CollapsibleCard from "../../../components/IndividualPageContent/CollapsibleCard";
import JsonViewCard from "../../../components/IndividualPageContent/JsonViewCard";

function ResourcesContent({
data,
resourceData,
}: {
data: Types.MoveResource[] | undefined;
resourceData: Types.MoveResource[] | undefined;
}): JSX.Element {
const resources: Types.MoveResource[] = data ?? [];
const resources: Types.MoveResource[] = resourceData ?? [];

const {expandedList, toggleExpandedAt, expandAll, collapseAll} =
useExpandedList(resources.length);
Expand Down Expand Up @@ -44,20 +42,9 @@ function ResourcesContent({
}

type ResourcesTabProps = {
address: string;
accountData: Types.AccountData | Types.MoveResource[] | undefined;
resourceData: Types.MoveResource[] | undefined;
};

export default function ResourcesTab({address}: ResourcesTabProps) {
const {isLoading, data, error} = useGetAccountResources(address);

if (isLoading) {
return null;
}

if (error) {
return <Error address={address} error={error} />;
}

return <ResourcesContent data={data} />;
export default function ResourcesTab({resourceData}: ResourcesTabProps) {
return <ResourcesContent resourceData={resourceData} />;
}
Loading

0 comments on commit e0928f7

Please sign in to comment.