11import { moduleToBase64 } from "app/(app)/(dashboard)/published-contract/utils/module-base-64" ;
22import { RocketIcon , ShieldCheckIcon } from "lucide-react" ;
3+ import { unstable_cache } from "next/cache" ;
34import Link from "next/link" ;
5+ import { resolveAvatar } from "thirdweb/extensions/ens" ;
46import { fetchPublishedContractVersion } from "@/api/contract/fetch-contracts-with-versions" ;
5- import { ClientOnly } from "@/components/blocks/client-only" ;
67import { Badge } from "@/components/ui/badge" ;
78import { Button } from "@/components/ui/button" ;
89import { Skeleton } from "@/components/ui/skeleton" ;
9- import { getClientThirdwebClient } from "@/constants/thirdweb-client.client" ;
1010import { serverThirdwebClient } from "@/constants/thirdweb-client.server" ;
11+ import { resolveEns } from "@/lib/ens" ;
1112import { replaceDeployerAddress } from "@/lib/publisher-utils" ;
1213import { cn } from "@/lib/utils" ;
1314import { resolveSchemeWithErrorHandler } from "@/utils/resolveSchemeWithErrorHandler" ;
1415import { ContractPublisher } from "./contract-publisher" ;
1516
16- interface ContractCardProps {
17+ type ContractCardProps = {
1718 publisher : string ;
1819 contractId : string ;
1920 titleOverride ?: string ;
@@ -29,7 +30,7 @@ interface ContractCardProps {
2930 moduleId : string ;
3031 version ?: string ;
3132 } [ ] ;
32- }
33+ } ;
3334
3435function getContractUrl (
3536 {
@@ -74,6 +75,72 @@ function getContractUrl(
7475 return replaceDeployerAddress ( pathName ) ;
7576}
7677
78+ const cached_fetchPublishedContractVersion = unstable_cache (
79+ async ( publisher : string , contractId : string , version : string = "latest" ) => {
80+ const result = await fetchPublishedContractVersion (
81+ publisher ,
82+ contractId ,
83+ serverThirdwebClient ,
84+ version ,
85+ ) . catch ( ( ) => null ) ;
86+
87+ if ( ! result ) {
88+ return null ;
89+ }
90+
91+ const publisherEnsAndAvatar = result . publisher
92+ ? await cached_resolvePublisherEnsAndAvatar ( result . publisher )
93+ : undefined ;
94+
95+ // Note: Do not return BigInt - it can't be serialized and cached by unstable_cache and will throw an error
96+ return {
97+ name : result . name ,
98+ displayName : result . displayName ,
99+ description : result . description ,
100+ publisher : {
101+ address : result . publisher ,
102+ ensName : publisherEnsAndAvatar ?. ensName ,
103+ ensAvatar : publisherEnsAndAvatar ?. ensAvatar ,
104+ } ,
105+ version : result . version ,
106+ audit : result . audit ,
107+ } ;
108+ } ,
109+ [ "fetchPublishedContractVersion" ] ,
110+ {
111+ revalidate : 3600 , // 1 hour
112+ } ,
113+ ) ;
114+
115+ const cached_resolvePublisherEnsAndAvatar = unstable_cache (
116+ async ( _addressOrEns : string ) => {
117+ const addressOrEns = replaceDeployerAddress ( _addressOrEns ) ;
118+ const [ ensNameInfo , ensAvatar ] = await Promise . allSettled ( [
119+ resolveEns ( addressOrEns , serverThirdwebClient ) ,
120+ resolveAvatar ( {
121+ client : serverThirdwebClient ,
122+ name : addressOrEns ,
123+ } ) ,
124+ ] ) ;
125+
126+ return {
127+ ensName :
128+ ensNameInfo . status === "fulfilled"
129+ ? ensNameInfo . value ?. ensName
130+ : undefined ,
131+ address :
132+ ensNameInfo . status === "fulfilled"
133+ ? ensNameInfo . value ?. address
134+ : undefined ,
135+ ensAvatar : ensAvatar . status === "fulfilled" ? ensAvatar . value : undefined ,
136+ } ;
137+ } ,
138+ [ "resolvePublisherEnsAndAvatar" ] ,
139+ {
140+ revalidate : 3600 , // 1 hour
141+ } ,
142+ ) ;
143+
77144export async function ContractCard ( {
78145 publisher,
79146 contractId,
@@ -83,12 +150,11 @@ export async function ContractCard({
83150 modules = [ ] ,
84151 isBeta,
85152} : ContractCardProps ) {
86- const publishedContractResult = await fetchPublishedContractVersion (
153+ const publishedContractResult = await cached_fetchPublishedContractVersion (
87154 publisher ,
88155 contractId ,
89- serverThirdwebClient ,
90156 version ,
91- ) . catch ( ( ) => null ) ;
157+ ) ;
92158
93159 if ( ! publishedContractResult ) {
94160 return null ;
@@ -186,13 +252,12 @@ export async function ContractCard({
186252 ! modules ?. length && "mt-auto" ,
187253 ) }
188254 >
189- { publishedContractResult . publisher && (
190- < ClientOnly ssr = { < Skeleton className = "size-5 rounded-full" /> } >
191- < ContractPublisher
192- addressOrEns = { publishedContractResult . publisher }
193- client = { getClientThirdwebClient ( ) }
194- />
195- </ ClientOnly >
255+ { publishedContractResult . publisher . address && (
256+ < ContractPublisher
257+ address = { publishedContractResult . publisher . address }
258+ ensName = { publishedContractResult . publisher . ensName || undefined }
259+ ensAvatar = { publishedContractResult . publisher . ensAvatar || undefined }
260+ />
196261 ) }
197262
198263 < div className = "flex items-center justify-between" >
0 commit comments