diff --git a/apps/web/app/CryptoProviders.tsx b/apps/web/app/CryptoProviders.tsx index d38e9f3d3df..83fdc66b265 100644 --- a/apps/web/app/CryptoProviders.tsx +++ b/apps/web/app/CryptoProviders.tsx @@ -50,7 +50,7 @@ const config = createConfig({ transports: { [base.id]: http(cdpBaseRpcEndpoint), [baseSepolia.id]: http(cdpBaseSepoliaRpcEndpoint), - [mainnet.id]: http(), + [mainnet.id]: http(process.env.NEXT_PUBLIC_MAINNET_RPC_URL), }, ssr: true, }); diff --git a/apps/web/app/api/ensip19/reverseName/route.ts b/apps/web/app/api/ensip19/reverseName/route.ts new file mode 100644 index 00000000000..b6547348fa9 --- /dev/null +++ b/apps/web/app/api/ensip19/reverseName/route.ts @@ -0,0 +1,36 @@ +import 'server-only'; +import { NextRequest } from 'next/server'; +import { Address, createPublicClient, http } from 'viem'; +import { base, mainnet } from 'viem/chains'; +import { convertChainIdToCoinTypeUint } from 'apps/web/src/utils/usernames'; + +export const dynamic = 'force-dynamic'; + +export async function GET(req: NextRequest) { + try { + const { searchParams } = new URL(req.url); + const address = searchParams.get('address') as Address | null; + if (!address) { + return new Response(JSON.stringify({ error: 'Missing address' }), { status: 400 }); + } + + const mainnetRpcUrl = process.env.MAINNET_RPC_URL || process.env.NEXT_PUBLIC_MAINNET_RPC_URL; + const client = createPublicClient({ + chain: mainnet, + transport: http(mainnetRpcUrl), + }); + + const coinType = BigInt(convertChainIdToCoinTypeUint(base.id)); + const name = await client.getEnsName({ address, coinType }); + + return new Response(JSON.stringify({ name: name ?? null }), { + status: 200, + headers: { 'content-type': 'application/json' }, + }); + } catch (e) { + return new Response(JSON.stringify({ name: null }), { + status: 200, + headers: { 'content-type': 'application/json' }, + }); + } +} diff --git a/apps/web/package.json b/apps/web/package.json index 0933be48d98..010bc69bb95 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -97,8 +97,8 @@ "typed.js": "^2.1.0", "usehooks-ts": "^3.1.0", "uuid": "^10.0.0", - "viem": "2.x", - "wagmi": "2.14.12", + "viem": "2.36.0", + "wagmi": "2.21.0", "zustand": "^5.0.5" }, "devDependencies": { diff --git a/apps/web/src/abis/L2ReverseRegistrarAbi.ts b/apps/web/src/abis/L2ReverseRegistrarAbi.ts index 3e7177900db..d8411b2cc2b 100644 --- a/apps/web/src/abis/L2ReverseRegistrarAbi.ts +++ b/apps/web/src/abis/L2ReverseRegistrarAbi.ts @@ -1,4 +1,23 @@ export default [ + { + type: 'function', + name: 'nameForAddr', + inputs: [ + { + name: 'addr', + type: 'address', + internalType: 'address', + }, + ], + outputs: [ + { + name: 'name', + type: 'string', + internalType: 'string', + }, + ], + stateMutability: 'view', + }, { type: 'function', name: 'setName', diff --git a/apps/web/src/components/ConnectWalletButton/ConnectWalletButton.tsx b/apps/web/src/components/ConnectWalletButton/ConnectWalletButton.tsx index 7fd22a41b00..8e87059e8e4 100644 --- a/apps/web/src/components/ConnectWalletButton/ConnectWalletButton.tsx +++ b/apps/web/src/components/ConnectWalletButton/ConnectWalletButton.tsx @@ -23,6 +23,7 @@ import { useCallback, useEffect, useState } from 'react'; import { useCopyToClipboard, useMediaQuery } from 'usehooks-ts'; import { useAccount, useSwitchChain } from 'wagmi'; import { DynamicCryptoProviders } from 'apps/web/app/CryptoProviders.dynamic'; +import useBaseEnsName from 'apps/web/src/hooks/useBaseEnsName'; export enum ConnectWalletButtonVariants { BaseOrg, @@ -64,6 +65,7 @@ export function ConnectWalletButton({ const { address, connector, isConnected, isConnecting, isReconnecting, chain } = useAccount(); const chainSupported = !!chain && supportedChainIds.includes(chain.id); const { basenameChain } = useBasenameChain(); + const { data: primaryName } = useBaseEnsName({ address: address as `0x${string}` | undefined }); const [, copy] = useCopyToClipboard(); const copyAddress = useCallback(() => void copy(address ?? ''), [address, copy]); @@ -140,7 +142,14 @@ export function ConnectWalletButton({
- {isDesktop && } + {isDesktop && ( + + )}
@@ -151,6 +160,7 @@ export function ConnectWalletButton({ onClick={copyAddress} chain={basenameChain} className="cursor-pointer font-display transition-all hover:opacity-65" + name={primaryName ?? undefined} /> diff --git a/apps/web/src/components/ConnectWalletButton/CustomWalletAdvancedAddressDetails.tsx b/apps/web/src/components/ConnectWalletButton/CustomWalletAdvancedAddressDetails.tsx index a58bd765b26..1a17635748b 100644 --- a/apps/web/src/components/ConnectWalletButton/CustomWalletAdvancedAddressDetails.tsx +++ b/apps/web/src/components/ConnectWalletButton/CustomWalletAdvancedAddressDetails.tsx @@ -4,9 +4,11 @@ import classNames from 'classnames'; import { useCallback, useState } from 'react'; import { useAccount } from 'wagmi'; import { useCopyToClipboard } from 'usehooks-ts'; +import useBaseEnsName from 'apps/web/src/hooks/useBaseEnsName'; export function CustomWalletAdvancedAddressDetails() { const { address, chain } = useAccount(); + const { data: primaryName } = useBaseEnsName({ address: address as `0x${string}` | undefined }); const [copyText, setCopyText] = useState('Copy'); const [, copy] = useCopyToClipboard(); @@ -52,6 +54,7 @@ export function CustomWalletAdvancedAddressDetails() { className={classNames( 'hover:text-[var(--ock-text-foreground-muted)] active:text-[var(--ock-text-primary)]', )} + name={primaryName ?? undefined} />