diff --git a/web/components/organisms/deploy/DeploySOResolver.tsx b/web/components/organisms/deploy/DeploySOResolver.tsx index dad8ef4..8022f7a 100644 --- a/web/components/organisms/deploy/DeploySOResolver.tsx +++ b/web/components/organisms/deploy/DeploySOResolver.tsx @@ -5,6 +5,7 @@ import { FC, useEffect, useMemo, useState } from "react"; import { useAccount, useChainId, useSimulateContract, useWriteContract } from "wagmi"; import { Address, formatEther } from "viem"; import { useDeployedResolvers } from "../../../stores/deployed_resolvers"; +import { SORDeployments } from "../../../util/deployments"; // https url that must include '{sender}' // const gatewayRegex = new RegExp("^https://.*{sender}.*$"); @@ -25,21 +26,6 @@ const subdomainChainMap = { 11155111: 'sepolia.' } -const deployments: Record = { - 1: { - factory: '0x77020a1Cb2d4a0AE6CC773Cc726c1EfdEC0a50ab', - }, - 5: { - factory: '0x2F180aDBAAb3c57af31B7E96969999D4FB33faEE', - }, - 11155111: { - factory: '0x0Fde82e81270431F2B956E7ce7E8860B2F61bcF9' - } -} - // Component that deploys the Simple Offchain Resolver\ // This resolver signs its output with a public private key-pair. export const DeployResolverCard: FC = () => { @@ -54,7 +40,7 @@ export const DeployResolverCard: FC = () => { const isReady = isGatewayUrlValid && isSignersValid; - const factoryAddress = deployments[chainId]?.factory; + const factoryAddress = SORDeployments[chainId]?.[0]?.factory; const { transactions, logTransaction, logTransactionSuccess } = useDeployedResolvers(); diff --git a/web/components/organisms/deployed_resolvers/DeployedResolver.tsx b/web/components/organisms/deployed_resolvers/DeployedResolver.tsx new file mode 100644 index 0000000..48cd528 --- /dev/null +++ b/web/components/organisms/deployed_resolvers/DeployedResolver.tsx @@ -0,0 +1,90 @@ +import { FC } from "react"; +import { TransactionState, TransactionStateDeployed, TransactionStatePending, useDeployedResolvers } from "../../../stores/deployed_resolvers"; +import { useChainId, useReadContract, useTransaction } from "wagmi"; +import { Button, Card, Input } from "@ensdomains/thorin"; +import { FiExternalLink, FiFile, FiTrash, FiTrash2 } from 'react-icons/fi'; +import { formatAddress } from '@ens-tools/format'; +import { explorer_urls } from "../../../util/deployments"; + +export const DeployedSOResolver: FC<{ transaction: TransactionStateDeployed }> = ({ transaction }) => { + const { data: gateway_data, error } = useReadContract({ + address: transaction.contract_address as any, + abi: [{ name: 'url', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ name: 'url', type: 'string' }] }] as const, + functionName: 'url', + chainId: Number.parseInt(transaction.chain), + args: [], + }); + const { data: transactionData } = useTransaction({ + hash: transaction.hash as `0x${string}`, + chainId: Number.parseInt(transaction.chain), + }); + + const explorer_url = explorer_urls[Number.parseInt(transaction.chain)]; + const gateway_url = gateway_data as string; + + return ( +
+
+
+
+ {/* */} + + + {formatAddress(transaction.contract_address)} + + + +
+
+ + Offchain Resolver + + on + + { + transaction.chain == "1" ? "Mainnet" : + transaction.chain == "5" ? "Goerli" : + transaction.chain == "11155111" ? "Sepolia" : "Unknown" + } + +
+
+ + Confirmed + +
+
+
+
Gateway URL
+
{gateway_data}
+
+ {/*
+
+ Total Gas Fees +
+
+ + 🔥 + + + { + formatEther( + transactionData?.gasPrice?.mul(transactionData?.gasLimit).toBigInt() ?? BigInt(0)) + } + +
+
*/} +
+ +
+ +
+
+
+
+ ) +}; \ No newline at end of file diff --git a/web/components/organisms/deployed_resolvers/DeployedResolvers.tsx b/web/components/organisms/deployed_resolvers/DeployedResolvers.tsx index f6d2809..76fcb3e 100644 --- a/web/components/organisms/deployed_resolvers/DeployedResolvers.tsx +++ b/web/components/organisms/deployed_resolvers/DeployedResolvers.tsx @@ -1,9 +1,9 @@ import { FC } from "react"; -import { TransactionState, TransactionStateDeployed, TransactionStatePending, useDeployedResolvers } from "../../../stores/deployed_resolvers"; -import { useChainId, useReadContract, useTransaction } from "wagmi"; -import { Button, Card, Input } from "@ensdomains/thorin"; -import { FiExternalLink, FiFile, FiTrash, FiTrash2 } from 'react-icons/fi'; -import { formatAddress } from '@ens-tools/format'; +import { TransactionState, useDeployedResolvers } from "../../../stores/deployed_resolvers"; +import { useChainId } from "wagmi"; +import { Card } from "@ensdomains/thorin"; +import { DeployedSOResolver } from "./DeployedResolver"; +import { TransactionHistoryEntry } from "./TransactionHistoryEntry"; export const DeployedResolvers = () => { const transactions = useDeployedResolvers(e => e.transactions); @@ -17,129 +17,15 @@ export const DeployedResolvers = () => {
-

Deployed Resolvers

+

Transactions

These are the resolvers you have deployed
{ - transactionForChain.map((transaction) => transaction.status == "deployed" ? - : ).reverse() + transactionForChain.map((transaction) => ) }
) }; - -export const PendingTransaction: FC<{ transaction: TransactionState }> = ({ transaction: { hash, chain } }) => { - - return ( -
-
Pending
-
{hash}
-
{chain}
-
- ); -}; - -const explorer_urls: Record = { - 1: { - transaction: 'https://etherscan.io/tx/:hash', - address: 'https://etherscan.io/address/:address' - }, - 5: { - transaction: 'https://goerli.etherscan.io/tx/:hash', - address: 'https://goerli.etherscan.io/address/:address' - }, - 11155111: { - transaction: 'https://sepolia.etherscan.io/tx/:hash', - address: 'https://sepolia.etherscan.io/address/:address' - }, -}; - -export const DeployedResolver: FC<{ transaction: TransactionStateDeployed }> = ({ transaction }) => { - const { data: gateway_data, error } = useReadContract({ - address: transaction.contract_address as any, - abi: [{ name: 'url', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ name: 'url', type: 'string' }] }] as const, - functionName: 'url', - chainId: Number.parseInt(transaction.chain), - args: [], - }); - const { data: transactionData } = useTransaction({ - hash: transaction.hash as `0x${string}`, - chainId: Number.parseInt(transaction.chain), - }); - - const explorer_url = explorer_urls[Number.parseInt(transaction.chain)]; - const gateway_url = gateway_data as string; - - return ( -
-
-
- -
- - Offchain Resolver - - on - - { - transaction.chain == "1" ? "Mainnet" : - transaction.chain == "5" ? "Goerli" : - transaction.chain == "11155111" ? "Sepolia" : "Unknown" - } - -
-
- - Confirmed - -
-
-
-
Gateway URL
-
{gateway_data || 'Unparsable'}
-
- {/*
-
- Total Gas Fees -
-
- - 🔥 - - - { - formatEther( - transactionData?.gasPrice?.mul(transactionData?.gasLimit).toBigInt() ?? BigInt(0)) - } - -
-
*/} -
- -
- -
-
-
-
- - ) -}; \ No newline at end of file diff --git a/web/components/organisms/deployed_resolvers/PendingResolver.tsx b/web/components/organisms/deployed_resolvers/PendingResolver.tsx new file mode 100644 index 0000000..f0aa9f7 --- /dev/null +++ b/web/components/organisms/deployed_resolvers/PendingResolver.tsx @@ -0,0 +1,47 @@ +import { FC, useEffect } from "react"; +import { FiExternalLink, FiLoader } from "react-icons/fi"; +import { TransactionStatePending, useDeployedResolvers } from "../../../stores/deployed_resolvers"; +import { explorer_urls } from "../../../util/deployments"; +import { useWaitForTransactionReceipt } from "wagmi"; + +export const PendingResolver: FC<{ transaction: TransactionStatePending }> = ({ transaction }) => { + const { data: receipt } = useWaitForTransactionReceipt({ + chainId: Number.parseInt(transaction.chain), + hash: transaction.hash as `0x${string}`, + }); + const {logTransactionSuccess} = useDeployedResolvers(); + + const explorer_url = explorer_urls[Number.parseInt(transaction.chain)]; + + useEffect(() => { + if (receipt) { + console.log('Transaction Completed', receipt); + logTransactionSuccess(transaction.hash, transaction.chain, receipt.to as string); + } + }, [receipt]); + + return ( +
+
+
+
+ {/* */} +
+
+ + + Offchain Resolver + + on + + {transaction.chain} + +
+
+ + Pending + +
+
+ ) +}; diff --git a/web/components/organisms/deployed_resolvers/TransactionHistoryEntry.tsx b/web/components/organisms/deployed_resolvers/TransactionHistoryEntry.tsx new file mode 100644 index 0000000..af59d40 --- /dev/null +++ b/web/components/organisms/deployed_resolvers/TransactionHistoryEntry.tsx @@ -0,0 +1,24 @@ +import { FC } from "react"; +import { TransactionState } from "../../../stores/deployed_resolvers"; +import { DeployedSOResolver } from "./DeployedResolver"; +import { PendingResolver } from "./PendingResolver"; + +export const TransactionHistoryEntry: FC<{ transaction: TransactionState }> = ({ transaction }) => { + if (transaction.status == 'pending') { + return ( + + ); + } + + if (transaction.status == 'deployed') { + return ( + + ); + } + + return ( +
+ Unknown Transaction Entry +
+ ); +}; diff --git a/web/stores/deployed_resolvers.tsx b/web/stores/deployed_resolvers.tsx index 0c80c63..9a1c4f5 100644 --- a/web/stores/deployed_resolvers.tsx +++ b/web/stores/deployed_resolvers.tsx @@ -6,6 +6,7 @@ export type TransactionStatePending = { hash: string; chain: string; }; + export type TransactionStateDeployed = { status: 'deployed'; hash: string; diff --git a/web/util/deployments.ts b/web/util/deployments.ts new file mode 100644 index 0000000..b869e31 --- /dev/null +++ b/web/util/deployments.ts @@ -0,0 +1,51 @@ +import { Address } from "viem"; +import { goerli, holesky, mainnet, sepolia } from "viem/chains"; + +type SORVersion = '1' | '2'; + +type SORDeployment = { + factory: Address, + version: SORVersion, +}; + +export const SORDeployments: Record = { + [mainnet.id]: [ + { + factory: '0x77020a1Cb2d4a0AE6CC773Cc726c1EfdEC0a50ab', + version: '1', + }, + ], + [goerli.id]: [ + { + factory: '0x2F180aDBAAb3c57af31B7E96969999D4FB33faEE', + version: '1', + }, + ], + [sepolia.id]: [ + { + factory: '0x0Fde82e81270431F2B956E7ce7E8860B2F61bcF9', + version: '1', + }, + ], + [holesky.id]: [ + // TODO: Deploy to Holesky + ], +}; + +export const explorer_urls: Record = { + 1: { + transaction: 'https://etherscan.io/tx/:hash', + address: 'https://etherscan.io/address/:address' + }, + 5: { + transaction: 'https://goerli.etherscan.io/tx/:hash', + address: 'https://goerli.etherscan.io/address/:address' + }, + 11155111: { + transaction: 'https://sepolia.etherscan.io/tx/:hash', + address: 'https://sepolia.etherscan.io/address/:address' + }, +};