From 720b5ffca4507556507c9b64c835c1342146c310 Mon Sep 17 00:00:00 2001 From: pheuberger Date: Sat, 15 Mar 2025 22:13:35 +0200 Subject: [PATCH 1/3] feat(profile): render warning banner on the server This caches the contract check on the server, so that our users don't have to run the same checks individually. --- .../profile/contract-accounts-banner.tsx | 10 +++---- lib/isContract.ts | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 lib/isContract.ts diff --git a/components/profile/contract-accounts-banner.tsx b/components/profile/contract-accounts-banner.tsx index 28c5113..43b3efd 100644 --- a/components/profile/contract-accounts-banner.tsx +++ b/components/profile/contract-accounts-banner.tsx @@ -1,11 +1,9 @@ -"use client"; +import { isContract } from "@/lib/isContract"; -import { useIsContract } from "@/hooks/useIsContract"; +export async function ContractAccountBanner({ address }: { address: string }) { + const isContractAddress = await isContract(address); -export function ContractAccountBanner({ address }: { address: string }) { - const { isContract, isLoading } = useIsContract(address); - - if (!isContract || isLoading) return null; + if (!isContractAddress) return null; return (
diff --git a/lib/isContract.ts b/lib/isContract.ts new file mode 100644 index 0000000..c4e79bf --- /dev/null +++ b/lib/isContract.ts @@ -0,0 +1,27 @@ +import { ChainFactory } from "./chainFactory"; +import { EvmClientFactory } from "./evmClient"; +import { unstable_cache } from "next/cache"; + +export const isContract = unstable_cache( + async (address: string) => { + 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}` }), + ), + ); + + return results.some( + (result) => + result.status === "fulfilled" && + result.value !== undefined && + result.value !== "0x", + ); + }, + ["isContract"], + { revalidate: 604800 }, // 1 week +); From 8bd66ba998b6899aac8a554fb7adfd6064144356 Mon Sep 17 00:00:00 2001 From: pheuberger Date: Wed, 12 Mar 2025 12:48:45 +0200 Subject: [PATCH 2/3] feat(profile): automatically switch to selected account Without this patch, selecting any other account other than your connected EOA using the account selector doesn't do anything on your profile page. However, we want people to be able to cycle through their accounts, so whenever another account is selected via the account selector, we want the profile page to redirect to that account. On the other hand we don't want the profile to automatically switch when the user is on a profile page that is not his connected EOA or one of the multisig they're a signer on. In these cases the selector will do nothing when the account selector is used. --- app/profile/[address]/page.tsx | 4 ++- components/profile/account-switcher.tsx | 41 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 components/profile/account-switcher.tsx diff --git a/app/profile/[address]/page.tsx b/app/profile/[address]/page.tsx index 45a4119..5f8e196 100644 --- a/app/profile/[address]/page.tsx +++ b/app/profile/[address]/page.tsx @@ -8,8 +8,9 @@ import { HypercertsTabContent } from "@/app/profile/[address]/hypercerts-tab-con import { CollectionsTabContent } from "@/app/profile/[address]/collections-tab-content"; 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"; +import { ProfileAccountSwitcher } from "@/components/profile/account-switcher"; + export default function ProfilePage({ params, searchParams, @@ -24,6 +25,7 @@ export default function ProfilePage({ return (
+

Profile diff --git a/components/profile/account-switcher.tsx b/components/profile/account-switcher.tsx new file mode 100644 index 0000000..021ad25 --- /dev/null +++ b/components/profile/account-switcher.tsx @@ -0,0 +1,41 @@ +"use client"; + +import { useAccount } from "wagmi"; +import { useEffect } from "react"; +import { useRouter } from "next/navigation"; + +import { useAccountStore } from "@/lib/account-store"; +import { useSafeAccounts } from "@/hooks/useSafeAccounts"; + +export function ProfileAccountSwitcher({ address }: { address: string }) { + const { address: connectedAddress } = useAccount(); + const { safeAccounts } = useSafeAccounts(); + const router = useRouter(); + const selectedAccount = useAccountStore((state) => state.selectedAccount); + + useEffect(() => { + if (!selectedAccount || !connectedAddress) return; + + const currentAddress = address.toLowerCase(); + const accounts = [ + { type: "eoa", address: connectedAddress }, + ...safeAccounts, + ]; + + // Find current account index + const currentIndex = accounts.findIndex( + (account) => account.address.toLowerCase() === currentAddress, + ); + + // If current address matches the connected address or a safe address the user is a signer on, + // and it's not the selected account, redirect to the selected account + if ( + currentIndex !== -1 && + currentAddress !== selectedAccount.address.toLowerCase() + ) { + router.push(`/profile/${selectedAccount.address}`); + } + }, [selectedAccount, address, connectedAddress, safeAccounts, router]); + + return null; +} From e9f28d9d3e7e6eb5d8ebf27d30f4b6ff4417bab9 Mon Sep 17 00:00:00 2001 From: pheuberger Date: Mon, 24 Mar 2025 20:22:11 +0200 Subject: [PATCH 3/3] fix(profile): reload claimable hypercerts When switching the accounts on the profile page, the unclaimed hypercerts tab wasn't reloaded. It was due to caching, so I removed that. It isn't a lot of data anyway. --- .../getAllowListRecordsForAddressByClaimed.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/allowlists/getAllowListRecordsForAddressByClaimed.tsx b/allowlists/getAllowListRecordsForAddressByClaimed.tsx index bc70ddd..78c83bc 100644 --- a/allowlists/getAllowListRecordsForAddressByClaimed.tsx +++ b/allowlists/getAllowListRecordsForAddressByClaimed.tsx @@ -42,10 +42,18 @@ export async function getAllowListRecordsForAddressByClaimed( address: string, claimed: boolean, ) { - const res = await request(HYPERCERTS_API_URL_GRAPH, query, { - address, - claimed, - }); + const res = await request( + HYPERCERTS_API_URL_GRAPH, + query, + { + address, + claimed, + }, + new Headers({ + "Cache-Control": "no-cache", + Pragma: "no-cache", + }), + ); const allowlistRecords = res.allowlistRecords.data; if (!allowlistRecords) {