Skip to content

Commit bc42c2f

Browse files
committed
[TOOL-3368] Dashboard: Improve page load perf of explore page and other few others (#6214)
<!-- start pr-codex --> ## PR-Codex overview This PR focuses on updating the contract fetching logic in the `dashboard` application to improve the retrieval of the latest published contracts. It replaces older functions with new ones that specifically fetch the latest contract versions. ### Detailed summary - Added `export const dynamic = "force-static";` to `page.tsx` files. - Replaced `getPublishedContractsWithPublisherMapping` with `getLatestPublishedContractsWithPublisherMapping` in multiple files. - Introduced `getLatestPublishedContractsWithPublisherMapping` function to fetch the latest contract version. - Updated `fetchPublishedContractVersions` to use `getSortedPublishedContractVersions`. - Created `fetchLatestPublishedContractVersion` for fetching the latest version details. - Modified `ContractCard` to use `ClientOnly` for rendering the `ContractPublisher`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent cad9c74 commit bc42c2f

File tree

9 files changed

+162
-83
lines changed

9 files changed

+162
-83
lines changed

apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/getModuleInstalledParams.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { getThirdwebClient } from "@/constants/thirdweb.server";
2-
import { fetchPublishedContractVersions } from "components/contract-components/fetch-contracts-with-versions";
2+
import {
3+
fetchLatestPublishedContractVersion,
4+
fetchPublishedContractVersions,
5+
} from "components/contract-components/fetch-contracts-with-versions";
36
import { isAddress } from "thirdweb";
7+
import type { FetchDeployMetadataResult } from "thirdweb/contract";
48
import { resolveAddress } from "thirdweb/extensions/ens";
59
import invariant from "tiny-invariant";
610
import type { ModuleMeta } from "./install-module-params";
@@ -14,16 +18,24 @@ export async function getModuleInstalledParams(ext: ModuleMeta) {
1418
client: getThirdwebClient(),
1519
name: ext.publisherAddress,
1620
});
17-
const allPublishedModules = await fetchPublishedContractVersions(
18-
publisherAddress,
19-
ext.moduleName,
20-
);
2121

22-
// find the version we want
23-
const publishedModule =
24-
ext.moduleVersion === "latest"
25-
? allPublishedModules[0]
26-
: allPublishedModules.find((v) => v.version === ext.moduleVersion);
22+
let publishedModule: FetchDeployMetadataResult | undefined = undefined;
23+
24+
if (ext.moduleVersion === "latest") {
25+
publishedModule = await fetchLatestPublishedContractVersion(
26+
publisherAddress,
27+
ext.moduleName,
28+
);
29+
} else {
30+
const allPublishedModules = await fetchPublishedContractVersions(
31+
publisherAddress,
32+
ext.moduleName,
33+
);
34+
35+
publishedModule = allPublishedModules.find(
36+
(v) => v.version === ext.moduleVersion,
37+
);
38+
}
2739

2840
invariant(
2941
publishedModule,

apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ContractPublishForm } from "components/contract-components/contract-pub
55
import { revalidatePath } from "next/cache";
66
import { notFound, redirect } from "next/navigation";
77
import { fetchDeployMetadata } from "thirdweb/contract";
8-
import { getPublishedContractsWithPublisherMapping } from "../../../published-contract/[publisher]/[contract_id]/utils/getPublishedContractsWithPublisherMapping";
8+
import { getLatestPublishedContractsWithPublisherMapping } from "../../../published-contract/[publisher]/[contract_id]/utils/getPublishedContractsWithPublisherMapping";
99

1010
type DirectDeployPageProps = {
1111
params: Promise<{
@@ -46,18 +46,16 @@ export default async function PublishContractPage(
4646
// - get the publish metadata with name+publisher address
4747
// - merge the two objects with publishMetadataFromUri taking higher precedence
4848
if (!publishMetadataFromUri.version) {
49-
const publishedContractVersions =
50-
await getPublishedContractsWithPublisherMapping({
49+
const publishedContract =
50+
await getLatestPublishedContractsWithPublisherMapping({
5151
publisher: address,
5252
contract_id: publishMetadataFromUri.name,
5353
});
5454

55-
if (!publishedContractVersions) {
55+
if (!publishedContract) {
5656
notFound();
5757
}
5858

59-
const publishedContract = publishedContractVersions[0];
60-
6159
if (publishedContract) {
6260
publishMetadata = {
6361
...publishedContract,

apps/dashboard/src/app/(dashboard)/explore/[category]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,5 @@ export default async function ExploreCategoryPage(
131131
</div>
132132
);
133133
}
134+
135+
export const dynamic = "force-static";

apps/dashboard/src/app/(dashboard)/explore/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,5 @@ export default async function ExplorePage() {
4848
</div>
4949
);
5050
}
51+
52+
export const dynamic = "force-static";

apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/layout.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { notFound } from "next/navigation";
21
import { PublishedContractBreadcrumbs } from "./components/breadcrumbs.client";
3-
import { getPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
2+
import { getLatestPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
43

54
type Params = { publisher: string; contract_id: string };
65

@@ -20,16 +19,11 @@ export async function generateMetadata(props: { params: Promise<Params> }) {
2019
const params = await props.params;
2120
const { publisher, contract_id } = params;
2221

23-
const publishedContracts = await getPublishedContractsWithPublisherMapping({
24-
publisher: publisher,
25-
contract_id: contract_id,
26-
});
27-
28-
if (!publishedContracts) {
29-
notFound();
30-
}
31-
32-
const publishedContract = publishedContracts[0];
22+
const publishedContract =
23+
await getLatestPublishedContractsWithPublisherMapping({
24+
publisher: publisher,
25+
contract_id: contract_id,
26+
});
3327

3428
if (!publishedContract) {
3529
return {

apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/opengraph-image.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { format } from "date-fns/format";
33
import { resolveEns } from "lib/ens";
44
import { correctAndUniqueLicenses } from "lib/licenses";
55
import { getSocialProfiles } from "thirdweb/social";
6-
import { getPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
6+
import { getLatestPublishedContractsWithPublisherMapping } from "./utils/getPublishedContractsWithPublisherMapping";
77
import { publishedContractOGImageTemplate } from "./utils/publishedContractOGImageTemplate";
88

99
export const runtime = "edge";
@@ -22,8 +22,8 @@ export default async function Image(props: {
2222
const client = getThirdwebClient();
2323
const { publisher, contract_id } = props.params;
2424

25-
const [publishedContracts, socialProfiles] = await Promise.all([
26-
getPublishedContractsWithPublisherMapping({
25+
const [publishedContract, socialProfiles] = await Promise.all([
26+
getLatestPublishedContractsWithPublisherMapping({
2727
publisher: publisher,
2828
contract_id: contract_id,
2929
}),
@@ -42,12 +42,6 @@ export default async function Image(props: {
4242
};
4343
})();
4444

45-
if (!publishedContracts) {
46-
return null;
47-
}
48-
49-
const publishedContract = publishedContracts[0];
50-
5145
if (!publishedContract) {
5246
return null;
5347
}

apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/utils/getPublishedContractsWithPublisherMapping.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { getThirdwebClient } from "@/constants/thirdweb.server";
2-
import { fetchPublishedContractVersions } from "components/contract-components/fetch-contracts-with-versions";
2+
import {
3+
fetchLatestPublishedContractVersion,
4+
fetchPublishedContractVersions,
5+
} from "components/contract-components/fetch-contracts-with-versions";
36
import { isAddress } from "thirdweb";
47
import { resolveAddress } from "thirdweb/extensions/ens";
58

@@ -36,3 +39,24 @@ export async function getPublishedContractsWithPublisherMapping(options: {
3639
return undefined;
3740
}
3841
}
42+
43+
export async function getLatestPublishedContractsWithPublisherMapping(options: {
44+
publisher: string;
45+
contract_id: string;
46+
}) {
47+
const { publisher, contract_id } = options;
48+
49+
try {
50+
// resolve ENS
51+
const publisherAddress = isAddress(publisher)
52+
? publisher
53+
: await resolveAddress({
54+
client: getThirdwebClient(),
55+
name: mapThirdwebPublisher(publisher),
56+
});
57+
58+
return fetchLatestPublishedContractVersion(publisherAddress, contract_id);
59+
} catch {
60+
return undefined;
61+
}
62+
}

apps/dashboard/src/components/contract-components/fetch-contracts-with-versions.ts

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getThirdwebClient } from "@/constants/thirdweb.server";
2-
import { isAddress } from "thirdweb";
2+
import { type ThirdwebClient, isAddress } from "thirdweb";
33
import { fetchDeployMetadata } from "thirdweb/contract";
44
import { resolveAddress } from "thirdweb/extensions/ens";
55
import {
@@ -20,22 +20,10 @@ export async function fetchPublishedContractVersions(
2020
contractId: string,
2121
) {
2222
const client = getThirdwebClient();
23-
const allVersions = await getPublishedContractVersions({
24-
contract: getContractPublisher(client),
25-
publisher: isAddress(publisherAddress)
26-
? publisherAddress
27-
: await resolveAddress({
28-
client,
29-
name: mapThirdwebPublisher(publisherAddress),
30-
}),
31-
contractId: contractId,
32-
});
33-
34-
const sortedVersions = allVersions.toSorted((a, b) => {
35-
if (a.publishTimestamp === b.publishTimestamp) {
36-
return 0;
37-
}
38-
return a.publishTimestamp > b.publishTimestamp ? -1 : 1;
23+
const sortedVersions = await getSortedPublishedContractVersions({
24+
publisherAddress,
25+
contractId,
26+
client,
3927
});
4028

4129
const responses = await Promise.allSettled(
@@ -61,21 +49,81 @@ export async function fetchPublishedContractVersions(
6149
return uniquePublishedContracts;
6250
}
6351

52+
async function getSortedPublishedContractVersions(params: {
53+
publisherAddress: string;
54+
contractId: string;
55+
client: ThirdwebClient;
56+
}) {
57+
const { publisherAddress, contractId, client } = params;
58+
59+
const allVersions = await getPublishedContractVersions({
60+
contract: getContractPublisher(client),
61+
publisher: isAddress(publisherAddress)
62+
? publisherAddress
63+
: await resolveAddress({
64+
client,
65+
name: mapThirdwebPublisher(publisherAddress),
66+
}),
67+
contractId: contractId,
68+
});
69+
70+
const sortedVersions = allVersions.toSorted((a, b) => {
71+
if (a.publishTimestamp === b.publishTimestamp) {
72+
return 0;
73+
}
74+
return a.publishTimestamp > b.publishTimestamp ? -1 : 1;
75+
});
76+
77+
return sortedVersions;
78+
}
79+
80+
export async function fetchLatestPublishedContractVersion(
81+
publisherAddress: string,
82+
contractId: string,
83+
) {
84+
const client = getThirdwebClient();
85+
86+
const sortedVersions = await getSortedPublishedContractVersions({
87+
publisherAddress,
88+
contractId,
89+
client,
90+
});
91+
92+
const latestVersion = sortedVersions[0];
93+
94+
if (!latestVersion) {
95+
return undefined;
96+
}
97+
98+
return fetchDeployMetadata({
99+
client,
100+
uri: latestVersion.publishMetadataUri,
101+
}).then((m) => ({ ...m, ...latestVersion }));
102+
}
103+
64104
export async function fetchPublishedContractVersion(
65105
publisherAddress: string,
66106
contractId: string,
67107
version = "latest",
68108
) {
109+
if (version === "latest") {
110+
const latestVersion = await fetchLatestPublishedContractVersion(
111+
publisherAddress,
112+
contractId,
113+
);
114+
115+
return latestVersion || null;
116+
}
117+
69118
const allVersions = await fetchPublishedContractVersions(
70119
publisherAddress,
71120
contractId,
72121
);
122+
73123
if (allVersions.length === 0) {
74124
return null;
75125
}
76-
if (version === "latest") {
77-
return allVersions[0];
78-
}
126+
79127
return allVersions.find((v) => v.version === version) || allVersions[0];
80128
}
81129

apps/dashboard/src/components/explore/contract-card/index.tsx

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { moduleToBase64 } from "app/(dashboard)/published-contract/utils/module-
99
import { replaceDeployerAddress } from "lib/publisher-utils";
1010
import { RocketIcon, ShieldCheckIcon } from "lucide-react";
1111
import Link from "next/link";
12+
import { ClientOnly } from "../../ClientOnly/ClientOnly";
1213
import { fetchPublishedContractVersion } from "../../contract-components/fetch-contracts-with-versions";
1314
import { ContractPublisher } from "../publisher";
1415

@@ -109,25 +110,6 @@ export async function ContractCard({
109110
"relative flex min-h-[220px] flex-col rounded-lg border border-border bg-card p-4 hover:border-active-border"
110111
}
111112
>
112-
<TrackedLinkTW
113-
className="absolute inset-0 z-0 cursor-pointer"
114-
href={getContractUrl({
115-
publisher,
116-
contractId,
117-
version,
118-
modules,
119-
titleOverride,
120-
})}
121-
category="contract_card"
122-
label={contractId}
123-
trackingProps={{
124-
publisher,
125-
contractId,
126-
version,
127-
...(tracking || {}),
128-
}}
129-
/>
130-
131113
{/* Audited + Version + Tags */}
132114
<div className="flex justify-between">
133115
<div className="flex items-center gap-1.5">
@@ -167,11 +149,30 @@ export async function ContractCard({
167149

168150
{/* Title */}
169151
<h3 className="font-semibold text-lg tracking-tight">
170-
{(
171-
titleOverride ||
172-
publishedContractResult.displayName ||
173-
publishedContractResult.name
174-
).replace("[Beta]", "")}
152+
<TrackedLinkTW
153+
className="cursor-pointer before:absolute before:inset-0 before:z-0"
154+
href={getContractUrl({
155+
publisher,
156+
contractId,
157+
version,
158+
modules,
159+
titleOverride,
160+
})}
161+
category="contract_card"
162+
label={contractId}
163+
trackingProps={{
164+
publisher,
165+
contractId,
166+
version,
167+
...(tracking || {}),
168+
}}
169+
>
170+
{(
171+
titleOverride ||
172+
publishedContractResult.displayName ||
173+
publishedContractResult.name
174+
).replace("[Beta]", "")}
175+
</TrackedLinkTW>
175176
</h3>
176177

177178
{/* Desc */}
@@ -198,7 +199,11 @@ export async function ContractCard({
198199
)}
199200
>
200201
{publishedContractResult.publisher && (
201-
<ContractPublisher addressOrEns={publishedContractResult.publisher} />
202+
<ClientOnly ssr={<Skeleton className="size-5 rounded-full" />}>
203+
<ContractPublisher
204+
addressOrEns={publishedContractResult.publisher}
205+
/>
206+
</ClientOnly>
202207
)}
203208

204209
<div className="flex items-center justify-between">

0 commit comments

Comments
 (0)