From 9d3bf451712641c5a8b0d8f6651b7cc6ec14e431 Mon Sep 17 00:00:00 2001 From: pheuberger Date: Sat, 15 Mar 2025 22:13:35 +0200 Subject: [PATCH 1/2] feat(profile): show warning banner contract account When viewing the profile of a smart contract address, there is a non-zero chance that the ownership across different networks varies. This could be exploitet, so it's best to prompt the users to do their own research. --- app/profile/[address]/page.tsx | 2 + .../profile/contract-accounts-banner.tsx | 18 +++++++ hooks/useIsContract.ts | 48 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 components/profile/contract-accounts-banner.tsx create mode 100644 hooks/useIsContract.ts diff --git a/app/profile/[address]/page.tsx b/app/profile/[address]/page.tsx index 0ceaac68..45a41194 100644 --- a/app/profile/[address]/page.tsx +++ b/app/profile/[address]/page.tsx @@ -9,6 +9,7 @@ import { CollectionsTabContent } from "@/app/profile/[address]/collections-tab-c import { MarketplaceTabContent } from "@/app/profile/[address]/marketplace-tab-content"; import { BlueprintsTabContent } from "@/app/profile/[address]/blueprint-tab-content"; +import { ContractAccountBanner } from "@/components/profile/contract-accounts-banner"; export default function ProfilePage({ params, searchParams, @@ -22,6 +23,7 @@ export default function ProfilePage({ return (
+

Profile diff --git a/components/profile/contract-accounts-banner.tsx b/components/profile/contract-accounts-banner.tsx new file mode 100644 index 00000000..28c5113d --- /dev/null +++ b/components/profile/contract-accounts-banner.tsx @@ -0,0 +1,18 @@ +"use client"; + +import { useIsContract } from "@/hooks/useIsContract"; + +export function ContractAccountBanner({ address }: { address: string }) { + const { isContract, isLoading } = useIsContract(address); + + if (!isContract || isLoading) return null; + + return ( +
+
+ This is a smart contract address. Contract ownership may vary across + networks. Please verify ownership details for each network. +
+
+ ); +} diff --git a/hooks/useIsContract.ts b/hooks/useIsContract.ts new file mode 100644 index 00000000..b74492a9 --- /dev/null +++ b/hooks/useIsContract.ts @@ -0,0 +1,48 @@ +import { useState, useEffect } from "react"; + +import { ChainFactory } from "../lib/chainFactory"; +import { EvmClientFactory } from "../lib/evmClient"; + +const contractCache = new Map(); + +export function useIsContract(address: string) { + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (isLoading || contractCache.has(address)) return; + + async function checkContract() { + setIsLoading(true); + try { + const supportedChains = ChainFactory.getSupportedChains(); + const clients = supportedChains.map((chainId) => + EvmClientFactory.createClient(chainId), + ); + + const results = await Promise.allSettled( + clients.map((client) => + client.getCode({ address: address as `0x${string}` }), + ), + ); + + const result = results.some( + (result) => + result.status === "fulfilled" && + result.value !== undefined && + result.value !== "0x", + ); + + contractCache.set(address, result); + } finally { + setIsLoading(false); + } + } + + checkContract(); + }, [address]); + + return { + isContract: contractCache.get(address) ?? null, + isLoading, + }; +} From 6fb7602789e8568efbcf8b7ee21ab331a2b200bf Mon Sep 17 00:00:00 2001 From: Satyam Mishra Date: Wed, 9 Apr 2025 13:02:48 +0530 Subject: [PATCH 2/2] feat: create a loading state while the hypercert data loads --- app/hypercerts/[hypercertId]/loading.tsx | 97 ++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 app/hypercerts/[hypercertId]/loading.tsx diff --git a/app/hypercerts/[hypercertId]/loading.tsx b/app/hypercerts/[hypercertId]/loading.tsx new file mode 100644 index 00000000..53be2b06 --- /dev/null +++ b/app/hypercerts/[hypercertId]/loading.tsx @@ -0,0 +1,97 @@ +import React from "react"; +import { Skeleton } from "@/components/ui/skeleton"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; + +const Loading = () => { + return ( +
+ {/* Hypercert Details Loading State */} +
+
+ {/* Image skeleton */} + + + {/* Content skeleton */} +
+ {/* Title */} + {/* ID */} + {/* Description */} + {/* Work scope */} +
+ +
+ + + +
+
+
+
+
+ + {/* Accordion Sections Loading State */} + + {/* Creator's Feed Section */} + + + CREATOR'S FEED + + +
+
+ +
+
+ + +
+
+
+
+ + {/* Evaluations Section */} + + + EVALUATIONS + + +
+
+ +
+
+ + +
+
+
+
+ + {/* Marketplace Section */} + + + MARKETPLACE + + +
+
+ + +
+
+ +
+
+
+
+
+
+ ); +}; + +export default Loading;