diff --git a/packages/nextjs/app/cow/_components/PoolConfiguration.tsx b/packages/nextjs/app/cow/_components/PoolConfiguration.tsx index a4bb70b..4845020 100644 --- a/packages/nextjs/app/cow/_components/PoolConfiguration.tsx +++ b/packages/nextjs/app/cow/_components/PoolConfiguration.tsx @@ -182,6 +182,7 @@ export const PoolConfiguration = () => { token2Amount, poolName, poolSymbol, + step: 1, }); }} /> diff --git a/packages/nextjs/app/cow/_components/PoolCreation.tsx b/packages/nextjs/app/cow/_components/PoolCreation.tsx index ce67ab8..6a40b40 100644 --- a/packages/nextjs/app/cow/_components/PoolCreation.tsx +++ b/packages/nextjs/app/cow/_components/PoolCreation.tsx @@ -1,11 +1,19 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { StepsDisplay } from "./StepsDisplay"; import { Address, parseUnits } from "viem"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { Alert, ExternalLinkButton, TextField, TokenField, TransactionButton } from "~~/components/common/"; -import { useBindPool, useCreatePool, useFinalizePool, useReadPool, useSetSwapFee } from "~~/hooks/cow/"; +import { + useBindPool, + useCreatePool, + useFinalizePool, + useNewPoolEvents, + useReadPool, + useSetSwapFee, +} from "~~/hooks/cow/"; import { getPoolUrl } from "~~/hooks/cow/getPoolUrl"; import { PoolCreationState } from "~~/hooks/cow/usePoolCreationState"; +import { usePoolCreationPersistedState } from "~~/hooks/cow/usePoolCreationState"; import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork"; import { useApproveToken, useReadToken } from "~~/hooks/token"; import { getBlockExplorerAddressLink } from "~~/utils/scaffold-eth"; @@ -18,9 +26,10 @@ interface ManagePoolCreationProps { export const PoolCreation = ({ state, clearState }: ManagePoolCreationProps) => { const token1RawAmount = parseUnits(state.token1Amount, state.token1.decimals); const token2RawAmount = parseUnits(state.token2Amount, state.token2.decimals); - const [currentStep, setCurrentStep] = useState(1); + const [userPoolAddress, setUserPoolAddress] = useState
(); + useNewPoolEvents(setUserPoolAddress); const { targetNetwork } = useTargetNetwork(); const isWrongNetwork = targetNetwork.id !== state.chainId; const { data: pool, refetch: refetchPool } = useReadPool(userPoolAddress); @@ -44,24 +53,27 @@ export const PoolCreation = ({ state, clearState }: ManagePoolCreationProps) => const { mutate: finalizePool, isPending: isFinalizePending, error: finalizeError } = useFinalizePool(); const txError = createPoolError || approveError || bindError || setSwapFeeError || finalizeError; + const setPersistedState = usePoolCreationPersistedState(state => state.setPersistedState); + const handleCreatePool = () => { - const payload = { name: state.poolName, symbol: state.poolSymbol }; - createPool(payload, { - onSuccess: newPoolAddress => { - setUserPoolAddress(newPoolAddress); - setCurrentStep(2); + createPool( + { name: state.poolName, symbol: state.poolSymbol }, + { + onSuccess: newPoolAddress => { + setUserPoolAddress(newPoolAddress); + setPersistedState({ ...state, step: 2 }); + }, }, - }); + ); }; const handleApproveTokens = async () => { - if (!pool) throw new Error("Pool address is required to approve tokens"); const txs = []; if (token1RawAmount > allowance1) { txs.push( approve({ token: state.token1.address, - spender: pool.address, + spender: pool?.address, rawAmount: token1RawAmount, }), ); @@ -70,53 +82,73 @@ export const PoolCreation = ({ state, clearState }: ManagePoolCreationProps) => txs.push( approve({ token: state.token2.address, - spender: pool.address, + spender: pool?.address, rawAmount: token2RawAmount, }), ); const results = await Promise.all(txs); - if (results.every(result => result === "success")) setCurrentStep(3); + if (results.every(result => result === "success")) setPersistedState({ ...state, step: 3 }); }; const handleBindTokens = async () => { - if (!pool) throw new Error("Required value is undefined in handleBindTokens"); - const poolTokens = pool.getCurrentTokens.map(token => token.toLowerCase()); - // If not already bound, bind the token const txs = []; - if (!poolTokens.includes(state.token1.address.toLowerCase())) { + // If not already bound, bind the token + const poolTokens = pool?.currentTokens.map(token => token.toLowerCase()); + if (!poolTokens?.includes(state.token1.address.toLowerCase())) { txs.push( bind({ - pool: pool.address, + pool: pool?.address, token: state.token1.address, rawAmount: token1RawAmount, }), ); } - if (!poolTokens.includes(state.token2.address.toLowerCase())) { + if (!poolTokens?.includes(state.token2.address.toLowerCase())) { txs.push( bind({ - pool: pool.address, + pool: pool?.address, token: state.token2.address, rawAmount: token2RawAmount, }), ); } const results = await Promise.all(txs); - if (results.every(result => result === "success")) setCurrentStep(4); + if (results.every(result => result === "success")) setPersistedState({ ...state, step: 4 }); }; const handleSetSwapFee = async () => { if (!pool) throw new Error("Pool is undefined in handleSetSwapFee"); - setSwapFee({ pool: pool.address, rawAmount: pool.MAX_FEE }, { onSuccess: () => setCurrentStep(5) }); + setSwapFee( + { pool: pool.address, rawAmount: pool.MAX_FEE }, + { onSuccess: () => setPersistedState({ ...state, step: 5 }) }, + ); }; const handleFinalize = async () => { - if (!pool) throw new Error("Pool is undefined in handleFinalize"); - finalizePool(pool.address, { - onSuccess: () => setCurrentStep(6), + finalizePool(pool?.address, { + onSuccess: () => setPersistedState({ ...state, step: 6 }), }); }; + useEffect(() => { + if (pool && pool.numTokens < 2n) { + if (allowance1 < token1RawAmount || allowance2 < token2RawAmount) { + setPersistedState({ ...state, step: 2 }); + } else { + setPersistedState({ ...state, step: 3 }); + } + } + if (pool && pool.numTokens === 2n && !pool.isFinalized) { + if (pool.swapFee !== pool.MAX_FEE) { + setPersistedState({ ...state, step: 4 }); + } else { + setPersistedState({ ...state, step: 5 }); + } + } + if (pool && pool.isFinalized && state.step !== 1) setPersistedState({ ...state, step: 6 }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pool, allowance1, allowance2, token1RawAmount, token2RawAmount]); + return ( <>