diff --git a/web/src/app/[cat]/InteractionClient.tsx b/web/src/app/[cat]/InteractionClient.tsx index 831d511e..869d88aa 100644 --- a/web/src/app/[cat]/InteractionClient.tsx +++ b/web/src/app/[cat]/InteractionClient.tsx @@ -21,7 +21,7 @@ import toast from "react-hot-toast"; import { catExplorer } from "@/utils/catExplorer"; // Define supported chain IDs -type SupportedChainId = 1 | 137 | 534351 | 5115 | 61 | 2001; +type SupportedChainId = 137 | 534351 | 5115 | 61 | 8453; interface TokenDetailsState { tokenName: string; @@ -80,9 +80,14 @@ export default function InteractionClient() { hash: revokeMinterRoleData, }); + // Add dialog open states + const [isMaxSupplyDialogOpen, setIsMaxSupplyDialogOpen] = useState(false); + const [isThresholdDialogOpen, setIsThresholdDialogOpen] = useState(false); + const [isExpansionRateDialogOpen, setIsExpansionRateDialogOpen] = useState(false); + // Type guard for chain ID validation const isValidChainId = useCallback((chainId: number): chainId is SupportedChainId => { - const validChainIds: SupportedChainId[] = [1, 137, 534351, 5115, 61, 2001]; + const validChainIds: SupportedChainId[] = [ 137, 534351, 5115, 61, 8453]; return validChainIds.includes(chainId as SupportedChainId); }, []); @@ -267,8 +272,11 @@ export default function InteractionClient() { chainId: chainId!, message: "Max supply updated successfully!", }); + // Refresh token details + getTokenDetails(); + setIsSigning(false); } - }, [reduceMaxSupplyData, chainId]); + }, [reduceMaxSupplyData, chainId, getTokenDetails]); useEffect(() => { if (reduceThresholdSupplyData) { @@ -277,8 +285,11 @@ export default function InteractionClient() { chainId: chainId!, message: "Threshold supply updated successfully!", }); + // Refresh token details + getTokenDetails(); + setIsSigning(false); } - }, [reduceThresholdSupplyData, chainId]); + }, [reduceThresholdSupplyData, chainId, getTokenDetails]); useEffect(() => { if (reduceMaxExpansionRateData) { @@ -287,8 +298,11 @@ export default function InteractionClient() { chainId: chainId!, message: "Max expansion rate updated successfully!", }); + // Refresh token details + getTokenDetails(); + setIsSigning(false); } - }, [reduceMaxExpansionRateData, chainId]); + }, [reduceMaxExpansionRateData, chainId, getTokenDetails]); useEffect(() => { if (disableTransferRestrictionData) { @@ -297,10 +311,36 @@ export default function InteractionClient() { chainId: chainId!, message: "Transfer restriction disabled successfully!", }); + // Refresh token details + getTokenDetails(); + setIsSigning(false); } - }, [disableTransferRestrictionData, chainId]); + }, [disableTransferRestrictionData, chainId, getTokenDetails]); + + useEffect(() => { + if (grantMinterRoleData) { + showTransactionToast({ + hash: grantMinterRoleData, + chainId: chainId!, + message: "Minter role granted successfully!", + }); + setMinterAddress(""); + setIsSigning(false); + } + }, [grantMinterRoleData, chainId]); + + useEffect(() => { + if (revokeMinterRoleData) { + showTransactionToast({ + hash: revokeMinterRoleData, + chainId: chainId!, + message: "Minter role revoked successfully!", + }); + setMinterAddress(""); + setIsSigning(false); + } + }, [revokeMinterRoleData, chainId]); - // Update the mint function to only show toast after transaction const handleMint = async () => { try { setIsSigning(true); @@ -322,7 +362,6 @@ export default function InteractionClient() { } }; - // Update the reduceMaxSupply function const handleReduceMaxSupply = async () => { try { setIsSigning(true); @@ -340,12 +379,10 @@ export default function InteractionClient() { success: false, message: "Failed to update max supply", }); - } finally { setIsSigning(false); } }; - // Update the reduceThresholdSupply function const handleReduceThresholdSupply = async () => { try { setIsSigning(true); @@ -363,12 +400,10 @@ export default function InteractionClient() { success: false, message: "Failed to update threshold supply", }); - } finally { setIsSigning(false); } }; - // Update the reduceMaxExpansionRate function const handleReduceMaxExpansionRate = async () => { try { setIsSigning(true); @@ -386,12 +421,10 @@ export default function InteractionClient() { success: false, message: "Failed to update max expansion rate", }); - } finally { setIsSigning(false); } }; - // Update the disableTransferRestriction function const handleDisableTransferRestriction = async () => { try { setIsSigning(true); @@ -408,7 +441,6 @@ export default function InteractionClient() { success: false, message: "Failed to disable transfer restriction", }); - } finally { setIsSigning(false); } }; @@ -435,7 +467,6 @@ export default function InteractionClient() { success: false, message: "Failed to grant minter role", }); - } finally { setIsSigning(false); } }; @@ -462,49 +493,15 @@ export default function InteractionClient() { success: false, message: "Failed to revoke minter role", }); - } finally { setIsSigning(false); } }; - useEffect(() => { - if (grantMinterRoleData) { - showTransactionToast({ - hash: grantMinterRoleData, - chainId: chainId!, - message: "Minter role granted successfully!", - }); - setMinterAddress(""); - } - }, [grantMinterRoleData, chainId]); - - useEffect(() => { - if (revokeMinterRoleData) { - showTransactionToast({ - hash: revokeMinterRoleData, - chainId: chainId!, - message: "Minter role revoked successfully!", - }); - setMinterAddress(""); - } - }, [revokeMinterRoleData, chainId]); - const handleCopyAddress = () => { navigator.clipboard.writeText(tokenAddress); toast.success("Address copied to clipboard!"); }; - // Add a polling effect to keep max mintable amount up to date - useEffect(() => { - if (tokenDetails.currentSupply >= tokenDetails.thresholdSupply) { - const interval = setInterval(() => { - getTokenDetails(); - }, 30000); // Update every 30 seconds - - return () => clearInterval(interval); - } - }, [tokenDetails.currentSupply, tokenDetails.thresholdSupply, getTokenDetails]); - if (isLoading) { return (

{tokenDetails.maxSupply} {tokenDetails.tokenSymbol}

- + - + Reduce Max Supply

@@ -581,7 +578,10 @@ export default function InteractionClient() {

- + Reduce Threshold Supply

@@ -632,7 +632,10 @@ export default function InteractionClient() {

- + Reduce Max Expansion Rate

@@ -683,7 +686,10 @@ export default function InteractionClient() {

) : ( -

- Transfers to any address are already enabled -

+ <> +

+ Transfers to any address are already enabled +

+ )} diff --git a/web/src/app/create/page.tsx b/web/src/app/create/page.tsx index 91f80069..955ad193 100644 --- a/web/src/app/create/page.tsx +++ b/web/src/app/create/page.tsx @@ -19,6 +19,7 @@ import { showTransactionToast } from "@/components/ui/transaction-toast"; import Link from "next/link"; import { LoadingState } from "@/components/ui/loading-state"; import { ButtonLoadingState } from "@/components/ui/button-loading-state"; +import { getPublicClient } from "@wagmi/core"; interface DeployContractProps { tokenName: string; @@ -189,13 +190,40 @@ export default function CreateCAT() { }; saveTransaction(txDetails); - showTransactionToast({ - hash: deployData, - chainId: config.state.chainId, - message: "CAT contract deployed successfully!", - }); - router.push("/my-cats"); - setIsDeploying(false); + + // Wait for transaction to be mined before showing success toast and redirecting + const checkTransaction = async () => { + try { + const publicClient = getPublicClient(config); + if (!publicClient) { + throw new Error("Public client not available"); + } + await publicClient.waitForTransactionReceipt({ hash: deployData }); + + showTransactionToast({ + hash: deployData, + chainId: config.state.chainId, + message: "CAT contract deployed successfully!", + }); + + // Add a small delay before redirecting to ensure the blockchain state is updated + setTimeout(() => { + router.push("/my-cats"); + setIsDeploying(false); + }, 2000); + } catch (error) { + console.error("Error waiting for transaction:", error); + showTransactionToast({ + hash: deployData, + chainId: config.state.chainId, + success: false, + message: "Failed to deploy CAT contract", + }); + setIsDeploying(false); + } + }; + + checkTransaction(); } }, [deployData, formData, router, saveTransaction]); diff --git a/web/src/app/my-cats/page.tsx b/web/src/app/my-cats/page.tsx index d1c1be2e..84a7a953 100644 --- a/web/src/app/my-cats/page.tsx +++ b/web/src/app/my-cats/page.tsx @@ -16,16 +16,15 @@ import { showTransactionToast } from "@/components/ui/transaction-toast"; import { LoadingState } from "@/components/ui/loading-state"; // Define supported chain IDs -type SupportedChainId = 1 | 137 | 534351 | 5115 | 61 | 2001; +type SupportedChainId = 137 | 534351 | 5115 | 61 | 8453; // Chain ID to name mapping const CHAIN_NAMES: Record = { - 1: "Ethereum", 137: "Polygon", 534351: "Scroll Sepolia", - 5115: "Citrea", + 5115: "Citrea Testnet", 61: "Ethereum Classic", - 2001: "Milkomeda" + 8453: "Base Mainnet", }; interface CatDetails { @@ -39,7 +38,7 @@ interface CatDetails { const isValidChainId = ( chainId: number | string ): chainId is SupportedChainId => { - const validChainIds: SupportedChainId[] = [1, 137, 534351, 5115, 61, 2001]; + const validChainIds: SupportedChainId[] = [ 137, 534351, 5115, 61, 8453]; return validChainIds.includes(Number(chainId) as SupportedChainId); }; diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index 802b9b04..3e8420e5 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -31,7 +31,8 @@ const supportedChains = [ { id: "534351", name: "Scroll Sepolia" }, { id: "5115", name: "Citrea" }, { id: "61", name: "Ethereum Classic" }, - { id: "2001", name: "Milkomeda" }, + { id: "8453", name: "Base Mainnet" }, + { id: "137", name: "Polygon Mainnet" }, ]; const contact_links = [ diff --git a/web/src/utils/address.ts b/web/src/utils/address.ts index 858a075d..ebf60d82 100644 --- a/web/src/utils/address.ts +++ b/web/src/utils/address.ts @@ -1,8 +1,10 @@ export const ClowderVaultFactories = { 534351: "0x543b2e68a257dc1edc6a75705cdb832e6fb87291", - // 5115: "0x1362ab4acAE43694b1A977484c3CE49C4341d482", - // 61: "0x0688f4E1c011529f9D4d5eAD2139659AeDA53cCE", + 5115: "0xA5afe3DD9F52797540deBd4dDc3fF83B5c5F37b6", + 61: "0x413377E435a439ed0c83D088B29677c011114310", // 2001: "0xef21ff9618506517536dd907a1467145fb6ab084", + 137: "0xddf55fae4603ce896fd7af2286c1e11e34bc252e", + 8453: "0xdc8db531c7138563e27d7a1074141568e361eb5c", } as { [key: number]: `0x${string}`; }; diff --git a/web/src/utils/catExplorer.ts b/web/src/utils/catExplorer.ts index 7495b70e..35b9fc9a 100644 --- a/web/src/utils/catExplorer.ts +++ b/web/src/utils/catExplorer.ts @@ -6,6 +6,8 @@ export const catExplorer = (hash: `0x${string}`, chainId: number): string => { 5115: "https://explorer.testnet.mantle.xyz/address/", 61: "https://explorer.testnet.rsk.co/address/", 2001: "https://explorer.testnet.milkomeda.com/address/", + 8453: "https://basescan.org/address/", + 84531: "https://goerli.basescan.org/address/", }; const baseUrl = baseUrls[chainId]; diff --git a/web/src/utils/config.tsx b/web/src/utils/config.tsx index f92b7989..30758375 100644 --- a/web/src/utils/config.tsx +++ b/web/src/utils/config.tsx @@ -2,6 +2,7 @@ import { mainnet, polygon, scrollSepolia, + base, } from "wagmi/chains"; import { getDefaultConfig, @@ -20,6 +21,7 @@ export const config = getDefaultConfig({ citreaTestnet, ethereumClassic, milkomeda, + base, ], ssr: true, }); diff --git a/web/src/utils/explorer.ts b/web/src/utils/explorer.ts index 11438618..d6a7aa60 100644 --- a/web/src/utils/explorer.ts +++ b/web/src/utils/explorer.ts @@ -6,6 +6,8 @@ export const getExplorerUrl = (hash: `0x${string}`, chainId: number): string => 5115: "https://explorer.testnet.mantle.xyz/tx/", 61: "https://explorer.testnet.rsk.co/tx/", 2001: "https://explorer.testnet.milkomeda.com/tx/", + 8453: "https://basescan.org/tx/", + 84531: "https://goerli.basescan.org/tx/", }; const baseUrl = baseUrls[chainId];