diff --git a/web/components/molecules/ContractOrGateway.tsx b/web/components/molecules/ContractOrGateway.tsx index d93f8f2..a3922b2 100644 --- a/web/components/molecules/ContractOrGateway.tsx +++ b/web/components/molecules/ContractOrGateway.tsx @@ -1,7 +1,8 @@ import { motion } from 'framer-motion'; -import { cx } from 'node:util/cx'; import { FC } from 'react'; +import { cx } from '../../util/cx'; + export const ContractOrRegister: FC<{ value: number; setValue: (value: number) => void; @@ -13,7 +14,7 @@ export const ContractOrRegister: FC<{ className="bg-ens-blue h-full w-[49%] rounded-md absolute left-0" animate={{ x: value === 0 ? 0 : '100%' }} > -
Contract -
-
+
+ ); diff --git a/web/components/molecules/ProfileButton.tsx b/web/components/molecules/ProfileButton.tsx index ccd6193..89eee17 100644 --- a/web/components/molecules/ProfileButton.tsx +++ b/web/components/molecules/ProfileButton.tsx @@ -1,6 +1,12 @@ import { Button, Profile, Select } from '@ensdomains/thorin'; import { useModal } from 'connectkit'; -import { useAccount, useChainId, useEnsAvatar, useEnsName, useSwitchChain } from 'wagmi'; +import { + useAccount, + useChainId, + useEnsAvatar, + useEnsName, + useSwitchChain, +} from 'wagmi'; export const ProfileButton = () => { const { setOpen } = useModal(); @@ -12,8 +18,7 @@ export const ProfileButton = () => { return (
- { - address && + {address && ( <> ({ value: chain.id.toString(), @@ -184,23 +185,31 @@ export const DeployResolverCard: FC = () => { This section of the site is undergoing maintenance to support multiple versions & networks. - {/* { + { (() => { if (!isConnected) return null; - if (receipt.isSuccess) return ( - - ); + // if (receipt.isSuccess) return ( + // + // ); return ( - ); })() - } */} + } ) }; diff --git a/web/components/organisms/deployed_resolvers/DeployedResolver.tsx b/web/components/organisms/deployed_resolvers/DeployedResolver.tsx index 6d233a2..cdd6a7a 100644 --- a/web/components/organisms/deployed_resolvers/DeployedResolver.tsx +++ b/web/components/organisms/deployed_resolvers/DeployedResolver.tsx @@ -4,11 +4,14 @@ import { useChainId, useReadContract, useTransaction } from "wagmi"; import { Button, Card, Input } from "@ensdomains/thorin"; import { FiChevronDown, FiChevronRight, FiChevronUp, FiExternalLink, FiFile, FiPenTool, FiTrash, FiTrash2 } from 'react-icons/fi'; import { formatAddress } from '@ens-tools/format'; -import { explorer_urls } from "../../../util/deployments"; +import { chainIdToName, explorer_urls } from "../../../util/deployments"; import { cx } from "../../../util/cx"; +import { SetUrlDialog } from "../set_url/SetUrlDialog"; +import { Address } from "viem"; export const DeployedSOResolver: FC<{ transaction: TransactionStateDeployed }> = ({ transaction }) => { const [collapsed, setCollapsed] = useState(true); + const [urlDialogOpen, setUrlDialogOpen] = useState(false); const { data: gateway_data, error } = useReadContract({ address: transaction.contract_address as any, @@ -45,9 +48,7 @@ export const DeployedSOResolver: FC<{ transaction: TransactionStateDeployed }> = on { - transaction.chain == "1" ? "Mainnet" : - transaction.chain == "5" ? "Goerli" : - transaction.chain == "11155111" ? "Sepolia" : "Unknown" + chainIdToName(Number.parseInt(transaction.chain)) }
@@ -96,7 +97,7 @@ export const DeployedSOResolver: FC<{ transaction: TransactionStateDeployed }> =
-
@@ -107,6 +108,9 @@ export const DeployedSOResolver: FC<{ transaction: TransactionStateDeployed }> = {collapsed ? 'Show Details' : 'Hide Details'} {collapsed ? : } + {urlDialogOpen && ( + { setUrlDialogOpen(false) }} /> + )} ) }; \ No newline at end of file diff --git a/web/components/organisms/set_url/SetUrlDialog.tsx b/web/components/organisms/set_url/SetUrlDialog.tsx new file mode 100644 index 0000000..823be90 --- /dev/null +++ b/web/components/organisms/set_url/SetUrlDialog.tsx @@ -0,0 +1,89 @@ +import { formatAddress } from "@ens-tools/format"; +import { Dialog, Button, Input } from "@ensdomains/thorin"; +import { FC, useState } from "react"; +import { FiCheck, FiX } from "react-icons/fi"; +import { chainIdToName, etherscanAddressURL } from "../../../util/deployments"; +import { Address } from "viem"; +import { useAccount, useReadContract, useWriteContract } from "wagmi"; + +export const SetUrlDialog: FC<{ chain: number, resolver: Address, current_value?: string, onClose?: () => void }> = ({ chain, resolver, current_value, onClose }) => { + const { address } = useAccount(); + const [newValue, setNewValue] = useState(current_value || ""); + const { writeContract, error } = useWriteContract({}); + const { data: owner } = useReadContract({ + address: resolver, + chainId: chain, + abi: [{ name: 'owner', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ name: 'owner', type: 'string' }] }] as const, + functionName: 'owner', + args: [] + }); + + const isOwner = owner == address; + const isReady = !!newValue && newValue !== current_value && isOwner; + + const chainName = chainIdToName(chain); + + return ( + { }} + > +
+ + {chainName} +
+ } + /> + setNewValue(e.target.value)} + /> + { + isOwner && +
+ + You are owner. +
+ } + { + !isOwner && owner && +
+ + You are NOT owner. (see {formatAddress(owner)}) +
+ } + { + !isOwner && !owner && +
+ + Ownership not available on this version. +
+ } + + +
+ ); +}; diff --git a/web/package.json b/web/package.json index 737d9ac..664f0be 100644 --- a/web/package.json +++ b/web/package.json @@ -32,6 +32,7 @@ "react-dom": "^18.3.1", "react-hook-form": "^7.51.3", "react-icons": "^4.12.0", + "react-modal": "^3.16.1", "styled-components": "^5.3.11", "tailwindcss": "^3.4.3", "viem": "^2.9.29", diff --git a/web/pages/globals.css b/web/pages/globals.css index bd83766..0f39b96 100644 --- a/web/pages/globals.css +++ b/web/pages/globals.css @@ -4,4 +4,19 @@ .link { @apply font-bold text-blue-500 hover:underline cursor-pointer; -} \ No newline at end of file +} + +.modal { + z-index: 1999; + position: fixed; + inset: 0; + background: rgba(0,0,0,0.5); +} + +.modal > div { + opacity: 1; +} + +#root { + z-index: 0; +} diff --git a/web/pages/main.tsx b/web/pages/main.tsx index 0d85a71..75c5dd5 100644 --- a/web/pages/main.tsx +++ b/web/pages/main.tsx @@ -2,8 +2,8 @@ import './globals.css'; import React from 'react'; import ReactDOM from 'react-dom/client'; +import Modal from 'react-modal'; -// import Modal from 'react-modal'; import { App } from './app.jsx'; ReactDOM.createRoot(document.querySelector('#root') as HTMLElement).render( @@ -12,4 +12,4 @@ ReactDOM.createRoot(document.querySelector('#root') as HTMLElement).render( ); -// Modal.setAppElement('#root'); +Modal.setAppElement('#root'); diff --git a/web/pages/thing.tsx b/web/pages/thing.tsx index 94541e0..2428f0a 100644 --- a/web/pages/thing.tsx +++ b/web/pages/thing.tsx @@ -1,7 +1,6 @@ import { lightTheme, ThorinGlobalStyles } from '@ensdomains/thorin'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ConnectKitProvider } from 'connectkit'; -import { ConnectKitButton } from 'connectkit'; import { FC, ReactNode } from 'react'; import { ThemeProvider } from 'styled-components'; import { createConfig, http, WagmiProvider } from 'wagmi'; diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index fdb0569..5217d15 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -62,6 +62,9 @@ dependencies: react-icons: specifier: ^4.12.0 version: 4.12.0(react@18.3.1) + react-modal: + specifier: ^3.16.1 + version: 3.16.1(react-dom@18.3.1)(react@18.3.1) styled-components: specifier: ^5.3.11 version: 5.3.11(@babel/core@7.24.5)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1) @@ -5868,6 +5871,10 @@ packages: strip-final-newline: 3.0.0 dev: false + /exenv@1.2.2: + resolution: {integrity: sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==} + dev: false + /extension-port-stream@3.0.0: resolution: {integrity: sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw==} engines: {node: '>=12.0.0'} @@ -8399,6 +8406,25 @@ packages: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} dev: false + /react-lifecycles-compat@3.0.4: + resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} + dev: false + + /react-modal@3.16.1(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==} + engines: {node: '>=8'} + peerDependencies: + react: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 + react-dom: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 + dependencies: + exenv: 1.2.2 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-lifecycles-compat: 3.0.4 + warning: 4.0.3 + dev: false + /react-native-webview@11.26.1(react-native@0.74.0)(react@18.3.1): resolution: {integrity: sha512-hC7BkxOpf+z0UKhxFSFTPAM4shQzYmZHoELa6/8a/MspcjEP7ukYKpuSUTLDywQditT8yI9idfcKvfZDKQExGw==} peerDependencies: @@ -9938,6 +9964,12 @@ packages: makeerror: 1.0.12 dev: false + /warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + dependencies: + loose-envify: 1.4.0 + dev: false + /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: diff --git a/web/util/deployments.ts b/web/util/deployments.ts index 6f6508c..8df7a67 100644 --- a/web/util/deployments.ts +++ b/web/util/deployments.ts @@ -52,3 +52,13 @@ export const explorer_urls: Record< address: 'https://sepolia.etherscan.io/address/:address', }, }; + +export const etherscanAddressURL = (chain: number, address: string) => { + return explorer_urls[chain].address.replace(':address', address); +} + +export const chainIdToName = (chainId: number) => { + return chainId == 1 ? "Mainnet" : + chainId == 5 ? "Goerli" : + chainId == 11155111 ? "Sepolia" : "Unknown"; +}