diff --git a/src/components/MintErrorModal.tsx b/src/components/MintErrorModal.tsx index 933ed37..defa14c 100644 --- a/src/components/MintErrorModal.tsx +++ b/src/components/MintErrorModal.tsx @@ -9,7 +9,7 @@ export const MintErrorModal: FC = (props) => { return (
-

Sorry, we couldn’t deploy your NFT smart countract.

+

Sorry, we couldn’t deploy your NFT smart contract.

Try again, and if there are still issues, please contact{" "} diff --git a/src/components/TokenForm/ConfirmStep.tsx b/src/components/TokenForm/ConfirmStep.tsx index a75cd7f..dedc9c8 100644 --- a/src/components/TokenForm/ConfirmStep.tsx +++ b/src/components/TokenForm/ConfirmStep.tsx @@ -8,12 +8,13 @@ import { IconArrowRight } from "../Icons/IconArrowRight"; import { useCollateralCheck, useDeploy } from "@/hooks/useDeploy"; import config from "@/config/configuration"; import { addProject } from "@/app/actions/add-project"; -import { useAccount } from "wagmi"; +import { useAccount, useSwitchChain } from "wagmi"; import { checkWhiteList } from "@/services/check-white-list"; import { toast } from "sonner"; import { Address } from "viem"; import { formatCurrencyAmount } from "@/helpers/currency"; import { usePolTokenPrice } from "@/hooks/usePolTokenPrice"; +import { useSwitchChainIfNeeded } from "@/hooks/useSwitchChainIfNeeded"; const ConfirmStep: React.FC<{ onNext: () => void; onBack: () => void }> = ({ onNext, @@ -22,7 +23,8 @@ const ConfirmStep: React.FC<{ onNext: () => void; onBack: () => void }> = ({ const [loading, setLoading] = useState(false); const { formData, setFormData } = useTokenFormContext(); const methods = useForm(); - const { address } = useAccount(); + const { address, chainId } = useAccount(); + const { switchChainAsync } = useSwitchChain(); const { handleSubmit, formState } = methods; const { deploy, prep, requestedModules, inverter } = useDeploy(); const collateralCheck = useCollateralCheck(); @@ -31,10 +33,19 @@ const ConfirmStep: React.FC<{ onNext: () => void; onBack: () => void }> = ({ const collateralUsdValueString: string = polTokenPrice.isSuccess ? formatCurrencyAmount(collateralAmount * polTokenPrice.data) : "-"; + const { switchChainIfNeeded } = useSwitchChainIfNeeded(); + const targetChain = config.SUPPORTED_CHAINS[0].id; // PolygonZkEvm chain ID const onSubmit = async (data: FormData) => { setLoading(true); + try { + // Return user to polygonZkEvm after deployed NFT contract on polygon + const chainSwitched = await switchChainIfNeeded(targetChain); + + // If chain switching failed, stop further execution + if (!chainSwitched) return; + const prepData = await prep.mutateAsync(); if (!address) throw new Error("Address not found"); diff --git a/src/components/TokenForm/NFTDeploymentStep.tsx b/src/components/TokenForm/NFTDeploymentStep.tsx index 3c603ab..89fee50 100644 --- a/src/components/TokenForm/NFTDeploymentStep.tsx +++ b/src/components/TokenForm/NFTDeploymentStep.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react"; import Image from "next/image"; import { Address } from "viem"; +import { useAccount, useSwitchChain } from "wagmi"; import StepNavigation from "./StepNavigation"; import { useTokenFormContext } from "./TokenFormContext"; @@ -9,6 +10,8 @@ import { MintSuccessModal } from "@/components/MintSuccessModal"; import { MintErrorModal } from "@/components/MintErrorModal"; import { useNFT } from "@/hooks/useNFT"; import { toast } from "sonner"; +import config from "@/config/configuration"; +import { useSwitchChainIfNeeded } from "@/hooks/useSwitchChainIfNeeded"; interface FormData { nftContractAddress?: Address; @@ -26,11 +29,21 @@ const NFTDeploymentStep: React.FC<{ const methods = useForm(); const { handleSubmit, formState } = methods; const { deploy } = useNFT(); + const { chainId } = useAccount(); + const { switchChainAsync } = useSwitchChain(); + const { switchChainIfNeeded } = useSwitchChainIfNeeded(); + const targetNFTChain = config.SUPPORTED_CHAINS[1].id; // Polygon chain ID const onSubmit = async (data: FormData) => { try { setLoading(true); + // Deploy NFT contract on the target chain: Polygon + const chainSwitched = await switchChainIfNeeded(targetNFTChain); + + // If chain switching failed, stop further execution + if (!chainSwitched) return; + const nftName = formData.tokenName.trim() + " NFT"; const nftSymbol = formData.tokenTicker.trim() + "NFT"; diff --git a/src/config/development.ts b/src/config/development.ts index e5fa67e..25391c6 100644 --- a/src/config/development.ts +++ b/src/config/development.ts @@ -4,7 +4,7 @@ import { Address } from "viem"; import { Chain, optimismSepolia, baseSepolia } from "wagmi/chains"; const config: EnvConfig = { - SUPPORTED_CHAINS: [baseSepolia] as [Chain], + SUPPORTED_CHAINS: [baseSepolia, baseSepolia] as [Chain, Chain], COLATERAL_TOKEN: "0x065775C7aB4E60ad1776A30DCfB15325d231Ce4F", // COLATERAL_SUPPLIER: "0x0000000000000000000000000000000000000000", GRAPHQL_ENDPOINT: diff --git a/src/config/production.ts b/src/config/production.ts index dadf9fd..a6d9e0f 100644 --- a/src/config/production.ts +++ b/src/config/production.ts @@ -1,9 +1,9 @@ import { EnvConfig } from "@/types/config"; import { Address } from "viem"; -import { Chain, polygonZkEvm } from "wagmi/chains"; +import { Chain, polygonZkEvm, polygon } from "wagmi/chains"; const config: EnvConfig = { - SUPPORTED_CHAINS: [polygonZkEvm] as [Chain], + SUPPORTED_CHAINS: [polygonZkEvm, polygon] as [Chain, Chain], COLATERAL_TOKEN: "0x0000000000000000000000000000000000000000" as Address, // COLATERAL_SUPPLIER: "0x0000000000000000000000000000000000000000", GRAPHQL_ENDPOINT: diff --git a/src/hooks/useSwitchChainIfNeeded.ts b/src/hooks/useSwitchChainIfNeeded.ts new file mode 100644 index 0000000..96989d3 --- /dev/null +++ b/src/hooks/useSwitchChainIfNeeded.ts @@ -0,0 +1,36 @@ +import { useAccount, useSwitchChain } from "wagmi"; +import { toast } from "sonner"; + +/** + * Custom React hook to switch the blockchain network if needed. + * This hook fetches the `chainId` from the connected account using wagmi and + * performs a chain switch using `switchChainAsync`. + * + * @param {number} targetChain - The chain ID you want to switch to. + * @returns {Promise} - Returns `true` if the switch is successful, otherwise `false`. + */ +export const useSwitchChainIfNeeded = () => { + const { chainId } = useAccount(); + const { switchChainAsync } = useSwitchChain(); + + const switchChainIfNeeded = async (targetChain: number): Promise => { + if (chainId !== targetChain) { + try { + const switchChainResponse = await switchChainAsync({ + chainId: targetChain, + }); + + if (switchChainResponse.id !== targetChain) { + toast.error("Failed to switch chain. Please switch manually."); + return false; + } + } catch (error) { + toast.error("Error while switching chain. Please try manually."); + return false; + } + } + return true; + }; + + return { switchChainIfNeeded }; +}; diff --git a/src/types/config.ts b/src/types/config.ts index 4189ea4..b4d835f 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -3,7 +3,7 @@ import { UserArgs } from "./inverter"; import type { inverterFactoryType } from "@/config/configuration"; export type EnvConfig = { - SUPPORTED_CHAINS: [Chain]; + SUPPORTED_CHAINS: [Chain, Chain]; COLATERAL_TOKEN: Address; COLATERAL_SUPPLIER?: Address; GRAPHQL_ENDPOINT: string;