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, + }; +}