diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseInfo/index.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseInfo/index.tsx index d3d38f5f..0261bd62 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseInfo/index.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseInfo/index.tsx @@ -1,4 +1,5 @@ import React, { useEffect } from "react"; +import { ChooseTokenAmounts } from "../../PoolCreation/ChooseTokenAmounts"; import { PoolType } from "@balancer/sdk"; import { sonic } from "viem/chains"; import { TextField } from "~~/components/common"; @@ -38,8 +39,8 @@ export const ChooseInfo = () => {
Choose pool information:
-
-
+
+
{ />
-
+
{
+
); }; diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/EclpParams.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/EclpParams.tsx index a5a64db1..5ae3e175 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/EclpParams.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/EclpParams.tsx @@ -1,10 +1,11 @@ import ReactECharts from "echarts-for-react"; -import { formatUnits, parseUnits } from "viem"; +import { formatUnits } from "viem"; import { ArrowTopRightOnSquareIcon, ArrowsRightLeftIcon } from "@heroicons/react/24/outline"; import { Alert, TextField } from "~~/components/common"; import { useAutofillStarterParams, useEclpParamValidations, useEclpPoolChart } from "~~/hooks/gyro"; +import { useInvertEclpParams } from "~~/hooks/gyro"; import { useFetchTokenRate, usePoolCreationStore, useUserDataStore } from "~~/hooks/v3"; -import { calculateRotationComponents, formatEclpParamValues } from "~~/utils/gryo"; +import { calculateRotationComponents } from "~~/utils/gryo"; import { truncateNumber } from "~~/utils/helpers"; export function EclpParams() { @@ -46,41 +47,8 @@ export function EclpParams() { export function EclpChartDisplay({ size }: { size: "full" | "mini" }) { const { options } = useEclpPoolChart(); - const { eclpParams, updateEclpParam, updatePool, tokenConfigs } = usePoolCreationStore(); - - /** - * SDK handles un-inversion for on chain call, - * so we just want to: - * 1. flip the tokenConfig order in pool creation store - * 2. invert the eclp params - * 3. make sure all parts of app rely on order of tokens in tokenConfigs - */ - const handleInvertEclpParams = () => { - const D18 = 10n ** 18n; - - const { alpha, beta, peakPrice, c, s, lambda, usdPerTokenInput0, usdPerTokenInput1 } = eclpParams; - - // take reciprocal and flip alpha to beta - const invertedAlpha = Number(formatUnits((D18 * D18) / parseUnits(beta, 18), 18)); - // take reciprocal and flip beta to alpha - const invertedBeta = Number(formatUnits((D18 * D18) / parseUnits(alpha, 18), 18)); - // take reciprocal of peakPrice - const invertedPeakPrice = Number(formatUnits((D18 * D18) / parseUnits(peakPrice, 18), 18)); - - const invertedParams = { - alpha: formatEclpParamValues(invertedAlpha), - beta: formatEclpParamValues(invertedBeta), - peakPrice: formatEclpParamValues(invertedPeakPrice), - c: s, // flip c and s - s: c, // flip s and c - usdPerTokenInput0: usdPerTokenInput1, - usdPerTokenInput1: usdPerTokenInput0, - lambda, // stays the same - }; - - updateEclpParam(invertedParams); - updatePool({ tokenConfigs: [...tokenConfigs].reverse() }); - }; + + const { invertEclpParams } = useInvertEclpParams(); return (
@@ -89,7 +57,7 @@ export function EclpChartDisplay({ size }: { size: "full" | "mini" }) { {size === "full" && (
diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/LiquidityManagement.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/LiquidityManagement.tsx index 0f5cdcf0..879d9d3f 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/LiquidityManagement.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseParameters/LiquidityManagement.tsx @@ -26,9 +26,9 @@ export function LiquidityManagement() { {poolType === PoolType.StableSurge ? (
-
- Stable Surge pools must set disable unbalanced liquidity to false - +
+ + Stable Surge pools must allow unbalanced liquidity operations
-
- Stable surge pools must use Balancer's stable surge hook +
+ Stable surge pools must use Balancer's stable surge hook
) : ( diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseTokens/ChooseToken.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseTokens/ChooseToken.tsx index ff188a41..8dca2c20 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseTokens/ChooseToken.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseTokens/ChooseToken.tsx @@ -67,6 +67,7 @@ export function ChooseToken({ index }: { index: number }) { tokenInfo: { ...tokenInfo }, useBoostedVariant: false, paysYieldFees: false, + amount: "", }); // Gross pattern but works for triggering new autofill of pool type specific params? diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseType/index.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseType/index.tsx index b174ee0e..b45102f9 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseType/index.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration/ChooseType/index.tsx @@ -7,14 +7,12 @@ export function ChooseType() { return ( <> -
-
-
Choose a pool type:
-
- {poolTypes.map((type: SupportedPoolTypes) => ( - - ))} -
+
+
Choose a pool type:
+
+ {poolTypes.map((type: SupportedPoolTypes) => ( + + ))}
diff --git a/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/ChooseTokenAmount.tsx b/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/ChooseTokenAmount.tsx index 94857e6c..180f5410 100644 --- a/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/ChooseTokenAmount.tsx +++ b/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/ChooseTokenAmount.tsx @@ -4,10 +4,19 @@ import { PoolType } from "@balancer/sdk"; import { useQueryClient } from "@tanstack/react-query"; import { erc20Abi, formatUnits } from "viem"; import { useAccount, useReadContract } from "wagmi"; +import { useEclpInitAmountsRatio } from "~~/hooks/gyro"; import { useTokenUsdValue } from "~~/hooks/token"; -import { type TokenConfig, usePoolCreationStore, useUserDataStore } from "~~/hooks/v3"; +import { type TokenConfig, useFetchTokenRate, usePoolCreationStore, useUserDataStore } from "~~/hooks/v3"; -export function ChooseTokenAmount({ index, tokenConfig }: { index: number; tokenConfig: TokenConfig }) { +export function ChooseTokenAmount({ + index, + tokenConfig, + useSuggestedAmounts, +}: { + index: number; + tokenConfig: TokenConfig; + useSuggestedAmounts: boolean; +}) { const { updateUserData, userTokenBalances } = useUserDataStore(); const { poolType, updateTokenConfig, eclpParams, tokenConfigs } = usePoolCreationStore(); const { tokenInfo, amount, address, weight } = tokenConfig; @@ -16,7 +25,6 @@ export function ChooseTokenAmount({ index, tokenConfig }: { index: number; token const [usdValue, setUsdValue] = useState(null); const queryClient = useQueryClient(); - const usdPerToken0 = Number(usdPerTokenInput0); const usdPerToken1 = Number(usdPerTokenInput1); @@ -44,10 +52,36 @@ export function ChooseTokenAmount({ index, tokenConfig }: { index: number; token return basePrice * Number(formatUnits(rate, 18)); }; + const { data: rateTokenA } = useFetchTokenRate(tokenConfigs[0].rateProvider); + const { data: rateTokenB } = useFetchTokenRate(tokenConfigs[1].rateProvider); + + const { alpha, beta, c, s, lambda } = eclpParams; + + const initAmountsRatio = useEclpInitAmountsRatio({ + alpha: Number(alpha), + beta: Number(beta), + c: Number(c), + s: Number(s), + lambda: Number(lambda), + rateA: rateTokenA ? +formatUnits(rateTokenA, 18) : 1, + rateB: rateTokenB ? +formatUnits(rateTokenB, 18) : 1, + }); + const handleAmountChange = (e: React.ChangeEvent) => { - const inputValue = e.target.value.trim(); - if (Number(inputValue) >= 0) { - updateTokenConfig(index, { amount: inputValue }); + const referenceAmount = Number(e.target.value.trim()); + if (referenceAmount >= 0) { + if (poolType === PoolType.GyroE && initAmountsRatio && useSuggestedAmounts) { + // app forces tokens to be sorted before offering init amounts inputs + const isReferenceAmountForTokenA = index === 0; + const otherIndex = isReferenceAmountForTokenA ? 1 : 0; + + const otherTokenAmount = isReferenceAmountForTokenA + ? referenceAmount / initAmountsRatio // If entering tokenA, divide to get tokenB amount + : referenceAmount * initAmountsRatio; // If entering tokenB, multiply to get tokenA amount + + updateTokenConfig(otherIndex, { amount: Math.abs(otherTokenAmount).toString() }); + } + updateTokenConfig(index, { amount: referenceAmount.toString() }); } else { updateTokenConfig(index, { amount: "" }); } diff --git a/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/index.tsx b/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/index.tsx index 4773abed..cb6c1ad5 100644 --- a/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/index.tsx +++ b/packages/nextjs/app/v3/_components/PoolCreation/ChooseTokenAmounts/index.tsx @@ -1,54 +1,76 @@ -import React from "react"; +import React, { useEffect, useRef, useState } from "react"; import { ChooseTokenAmount } from "./ChooseTokenAmount"; import { PoolType } from "@balancer/sdk"; -import { XMarkIcon } from "@heroicons/react/24/outline"; -import { Alert, TransactionButton } from "~~/components/common"; -import { usePoolCreationStore, useUserDataStore, useValidateInitializationInputs } from "~~/hooks/v3"; +import { Alert } from "~~/components/common"; +import { Checkbox } from "~~/components/common"; +import { useInvertEclpParams } from "~~/hooks/gyro"; +import { usePoolCreationStore, useUserDataStore } from "~~/hooks/v3"; export function ChooseTokenAmounts() { - const { tokenConfigs, poolType, updatePool, step, setIsChooseTokenAmountsModalOpen } = usePoolCreationStore(); + const [useSuggestedAmounts, setUseSuggestedAmounts] = useState(false); + const { tokenConfigs, poolType } = usePoolCreationStore(); const { updateUserData, hasAgreedToWarning } = useUserDataStore(); - const { isInitializePoolInputsValid } = useValidateInitializationInputs(); + + const isGyroEclp = poolType === PoolType.GyroE; + const isWeightedPool = poolType === PoolType.Weighted; + + const isTokenConfigsSorted = tokenConfigs.every((token, index) => { + if (index === 0) return true; + return token.address.toLowerCase() >= tokenConfigs[index - 1].address.toLowerCase(); + }); + + const shouldInvertEclpParams = !isTokenConfigsSorted && poolType === PoolType.GyroE; + + const { invertEclpParams } = useInvertEclpParams(); + const hasInvertedRef = useRef(false); + + // force token configs to be sorted in order before user enters amounts + useEffect(() => { + if (shouldInvertEclpParams && !hasInvertedRef.current) { + invertEclpParams(); + hasInvertedRef.current = true; + } + }, [shouldInvertEclpParams, invertEclpParams]); return ( -
-
- -
Choose Token Amounts
-
- {tokenConfigs.map((tokenConfig, index) => ( - - ))} -
- - {poolType === PoolType.Weighted && ( - - - - )} +
+
Choose initialization amounts:
- { - updatePool({ step: step + 1 }); - setIsChooseTokenAmountsModalOpen(false); - }} - title="Confirm Amounts" - isDisabled={!isInitializePoolInputsValid} - isPending={false} - /> +
+ {isGyroEclp && ( + { + setUseSuggestedAmounts(!useSuggestedAmounts); + }} + /> + )} + {tokenConfigs.map((tokenConfig, index) => ( + + ))}
+ + {isWeightedPool && ( + + + + )}
); } diff --git a/packages/nextjs/app/v3/_components/PoolCreation/index.tsx b/packages/nextjs/app/v3/_components/PoolCreation/index.tsx index 723c7caa..a55522c2 100644 --- a/packages/nextjs/app/v3/_components/PoolCreation/index.tsx +++ b/packages/nextjs/app/v3/_components/PoolCreation/index.tsx @@ -1,7 +1,6 @@ import { PoolDetails } from "../PoolDetails"; import { SupportAndResetModals } from "../SupportAndResetModals"; import { ApproveOnTokenManager } from "./ApproveOnTokenManager"; -import { ChooseTokenAmounts } from "./ChooseTokenAmounts"; import { PoolCreatedView } from "./PoolCreatedView"; import { Alert, PoolStepsDisplay, TransactionButton } from "~~/components/common"; import { useIsHyperEvm, useIsUsingBigBlocks, useToggleBlockSize } from "~~/hooks/hyperliquid"; @@ -21,17 +20,7 @@ import { getBlockExplorerTxLink } from "~~/utils/scaffold-eth"; * Manages the pool creation process using a modal that cannot be closed after execution of the first step */ export function PoolCreation({ setIsModalOpen }: { setIsModalOpen: (isOpen: boolean) => void }) { - const { - step, - tokenConfigs, - createPoolTx, - swapToBoostedTx, - initPoolTx, - chain, - poolAddress, - isChooseTokenAmountsModalOpen, - setIsChooseTokenAmountsModalOpen, - } = usePoolCreationStore(); + const { step, tokenConfigs, createPoolTx, swapToBoostedTx, initPoolTx, chain, poolAddress } = usePoolCreationStore(); const { data: boostableWhitelist } = useBoostableWhitelist(); const { mutate: createPool, isPending: isCreatePoolPending, error: createPoolError } = useCreatePool(); @@ -55,18 +44,6 @@ export function PoolCreation({ setIsModalOpen }: { setIsModalOpen: (isOpen: bool error: createPoolError || fetchPoolAddressError, }); - const chooseAmountsStep = { - label: "Choose Amounts", - component: ( - setIsChooseTokenAmountsModalOpen(true)} - title="Choose Token Amounts" - isDisabled={false} - isPending={false} - /> - ), - }; - const approveOnTokenSteps = tokenConfigs.map((token, idx) => { const { address, amount, tokenInfo } = token; const { decimals, symbol } = tokenInfo || {}; @@ -169,7 +146,6 @@ export function PoolCreation({ setIsModalOpen }: { setIsModalOpen: (isOpen: bool ...(showUseBigBlocksStep ? [useToggleBlockSizeStep] : []), deployStep, ...(showUseSmallBlocksStep ? [useToggleBlockSizeStep] : []), - chooseAmountsStep, ...approveOnTokenSteps, ...swapToBoostedStep, ...approveOnBoostedVariantSteps, @@ -217,7 +193,6 @@ export function PoolCreation({ setIsModalOpen }: { setIsModalOpen: (isOpen: bool
- {isChooseTokenAmountsModalOpen && } ); } diff --git a/packages/nextjs/app/v3/_components/PoolDetails.tsx b/packages/nextjs/app/v3/_components/PoolDetails.tsx index 06eac9a2..5811dea8 100644 --- a/packages/nextjs/app/v3/_components/PoolDetails.tsx +++ b/packages/nextjs/app/v3/_components/PoolDetails.tsx @@ -1,14 +1,8 @@ "use client"; -import { EclpChartDisplay } from "./PoolConfiguration/ChooseParameters/EclpParams"; import { PoolType } from "@balancer/sdk"; import { zeroAddress } from "viem"; -import { - ArrowTopRightOnSquareIcon, - CheckCircleIcon, - PencilSquareIcon, - QuestionMarkCircleIcon, -} from "@heroicons/react/24/outline"; +import { ArrowTopRightOnSquareIcon, CheckCircleIcon, QuestionMarkCircleIcon } from "@heroicons/react/24/outline"; import { TokenImage, TokenToolTip } from "~~/components/common"; import { useTargetNetwork } from "~~/hooks/scaffold-eth"; import { @@ -41,9 +35,6 @@ export function PoolDetails({ isPreview }: { isPreview?: boolean }) { reClammParams, isDelegatingPauseManagement, isDelegatingSwapFeeManagement, - step, - setIsChooseTokenAmountsModalOpen, - selectedTab, chain, } = usePoolCreationStore(); const { poolHooksWhitelist } = usePoolHooksWhitelist(chain?.id); @@ -56,12 +47,9 @@ export function PoolDetails({ isPreview }: { isPreview?: boolean }) { const poolDeploymentUrl = poolAddress ? getBlockExplorerAddressLink(targetNetwork, poolAddress) : undefined; - const isGyroEclp = poolType === PoolType.GyroE; const isStablePool = poolType === PoolType.Stable || poolType === PoolType.StableSurge; const isReClamm = poolType === PoolType.ReClamm; - const showMiniEclpChart = isGyroEclp && selectedTab === "Information"; - const poolHooksName = poolHooksWhitelist.find( hook => hook.value.toLowerCase() === poolHooksContract.toLowerCase(), )?.label; @@ -81,17 +69,7 @@ export function PoolDetails({ isPreview }: { isPreview?: boolean }) { isValid={isTokensValid} isEmpty={tokenConfigs.every(token => token.address === zeroAddress)} content={ -
- {(step === 2 || step === 3) && ( -
-
setIsChooseTokenAmountsModalOpen(true)} - > - -
-
- )} +
{tokenConfigs.map((token, index) => ( ))} @@ -106,11 +84,6 @@ export function PoolDetails({ isPreview }: { isPreview?: boolean }) { isEmpty={false} content={
- {showMiniEclpChart && ( -
- -
- )} {isStablePool && (
Amplification Parameter
diff --git a/packages/nextjs/hooks/gyro/index.ts b/packages/nextjs/hooks/gyro/index.ts index 4854d9c9..2c57dd6a 100644 --- a/packages/nextjs/hooks/gyro/index.ts +++ b/packages/nextjs/hooks/gyro/index.ts @@ -4,3 +4,5 @@ export * from "./drawLiquidityECLP"; export * from "./useValidateEclpParams"; export * from "./useAutofillStarterParams"; export * from "./useEclpSpotPrice"; +export * from "./useEclpInitAmountsRatio"; +export * from "./useInvertEclpParams"; diff --git a/packages/nextjs/hooks/gyro/useEclpInitAmountsRatio.ts b/packages/nextjs/hooks/gyro/useEclpInitAmountsRatio.ts new file mode 100644 index 00000000..1f96ed5b --- /dev/null +++ b/packages/nextjs/hooks/gyro/useEclpInitAmountsRatio.ts @@ -0,0 +1,38 @@ +import { useEclpSpotPrice } from "./useEclpSpotPrice"; + +type UseEclpInitAmountsRatio = { + alpha: number; + beta: number; + c: number; + s: number; + lambda: number; + rateA: number; + rateB: number; +}; + +/** + * helper function for calculation of proper token amounts for ECLP initialization + * logic provided by @joaobrunoah + */ +export function useEclpInitAmountsRatio({ alpha, beta, c, s, lambda, rateA, rateB }: UseEclpInitAmountsRatio) { + const { poolSpotPrice: spotPriceWithoutRate } = useEclpSpotPrice(); + if (!spotPriceWithoutRate || !alpha || !beta || !c || !s || !lambda || !rateA || !rateB) return undefined; + + const rHint = 1000; + const tauAlpha = getTau(alpha, c, s, lambda); + const tauBeta = getTau(beta, c, s, lambda); + const tauSpotPrice = getTau(spotPriceWithoutRate, c, s, lambda); + + const amountTokenA = + rateA * rHint * (c * lambda * tauBeta[0] + s * tauBeta[1]) - (c * lambda * tauSpotPrice[0] + s * tauSpotPrice[1]); + const amountTokenB = + rateB * rHint * (-s * lambda * tauAlpha[0] + c * tauAlpha[1]) - + (-s * lambda * tauSpotPrice[0] + c * tauSpotPrice[1]); + const ratio = amountTokenA / amountTokenB; + + return ratio; +} + +function getTau(price: number, c: number, s: number, lambda: number) { + return [price * c - s, (c + s * price) / lambda]; +} diff --git a/packages/nextjs/hooks/gyro/useInvertEclpParams.ts b/packages/nextjs/hooks/gyro/useInvertEclpParams.ts new file mode 100644 index 00000000..488d351b --- /dev/null +++ b/packages/nextjs/hooks/gyro/useInvertEclpParams.ts @@ -0,0 +1,36 @@ +import { useCallback } from "react"; +import { usePoolCreationStore } from "../v3"; +import { formatUnits, parseUnits } from "viem"; +import { formatEclpParamValues } from "~~/utils/gryo"; + +const D18 = 10n ** 18n; + +export function useInvertEclpParams() { + const { eclpParams, updateEclpParam, updatePool, tokenConfigs } = usePoolCreationStore(); + + const invertEclpParams = useCallback(() => { + const { alpha, beta, peakPrice, c, s, usdPerTokenInput0, usdPerTokenInput1 } = eclpParams; + + const invertedAlpha = Number(formatUnits((D18 * D18) / parseUnits(alpha, 18), 18)); + const invertedBeta = Number(formatUnits((D18 * D18) / parseUnits(beta, 18), 18)); + const invertedPeakPrice = Number(formatUnits((D18 * D18) / parseUnits(peakPrice, 18), 18)); + + const invertedParams = { + alpha: formatEclpParamValues(invertedBeta), // flip alpha to inverted beta + beta: formatEclpParamValues(invertedAlpha), // flip beta to inverted alpha + peakPrice: formatEclpParamValues(invertedPeakPrice), + c: s, // flip c to s + s: c, // flip s to c + usdPerTokenInput0: usdPerTokenInput1, + usdPerTokenInput1: usdPerTokenInput0, + }; + + // Use a timeout to ensure this update happens after other effects + setTimeout(() => { + updateEclpParam(invertedParams); + updatePool({ tokenConfigs: [...tokenConfigs].reverse() }); + }, 0); + }, [eclpParams, updateEclpParam, updatePool, tokenConfigs]); + + return { invertEclpParams }; +} diff --git a/packages/nextjs/hooks/v3/usePoolCreationStore.ts b/packages/nextjs/hooks/v3/usePoolCreationStore.ts index 76ccd020..fee49d5d 100644 --- a/packages/nextjs/hooks/v3/usePoolCreationStore.ts +++ b/packages/nextjs/hooks/v3/usePoolCreationStore.ts @@ -70,8 +70,6 @@ export interface PoolCreationStore { swapToBoostedTx: TransactionDetails; eclpParams: EclpParams; reClammParams: ReClammParams; - isChooseTokenAmountsModalOpen: boolean; - setIsChooseTokenAmountsModalOpen: (isOpen: boolean) => void; updatePool: (updates: Partial) => void; updateTokenConfig: (index: number, updates: Partial) => void; updateEclpParam: (updates: Partial) => void; @@ -149,8 +147,6 @@ export const usePoolCreationStore = create( set => ({ ...initialPoolCreationState, updatePool: (updates: Partial) => set(state => ({ ...state, ...updates })), - setIsChooseTokenAmountsModalOpen: (isOpen: boolean) => - set(state => ({ ...state, isChooseTokenAmountsModalOpen: isOpen })), updateTokenConfig: (index: number, updates: Partial) => set(state => { const newTokenConfigs = [...state.tokenConfigs]; diff --git a/packages/nextjs/hooks/v3/useValidateCreationInputs.ts b/packages/nextjs/hooks/v3/useValidateCreationInputs.ts index b8f314ed..653aac0c 100644 --- a/packages/nextjs/hooks/v3/useValidateCreationInputs.ts +++ b/packages/nextjs/hooks/v3/useValidateCreationInputs.ts @@ -2,7 +2,7 @@ import { PoolType, STABLE_POOL_CONSTRAINTS, TokenType } from "@balancer/sdk"; import { useQueryClient } from "@tanstack/react-query"; import { isAddress } from "viem"; import { useEclpParamValidations } from "~~/hooks/gyro"; -import { usePoolCreationStore, useValidateHooksContract } from "~~/hooks/v3"; +import { usePoolCreationStore, useValidateHooksContract, useValidateInitializationInputs } from "~~/hooks/v3"; import { MAX_POOL_NAME_LENGTH, MAX_POOL_SYMBOL_LENGTH } from "~~/utils/constants"; export function useValidateCreationInputs() { @@ -26,6 +26,8 @@ export function useValidateCreationInputs() { const { baseParamsError, derivedParamsError } = useEclpParamValidations(eclpParams); + const { isInitializePoolInputsValid } = useValidateInitializationInputs(); + const isTypeValid = poolType !== undefined; const isValidTokenWeights = @@ -47,7 +49,6 @@ export function useValidateCreationInputs() { } return true; }) && isValidTokenWeights; - // Check tanstack query cache for pool hooks contract validity const { isValidPoolHooksContract } = useValidateHooksContract(poolHooksContract); @@ -79,7 +80,8 @@ export function useValidateCreationInputs() { symbol.length <= MAX_POOL_SYMBOL_LENGTH && isValidTokenWeights; - const isPoolCreationInputValid = isTypeValid && isTokensValid && isParametersValid && isInfoValid; + const isPoolCreationInputValid = + isTypeValid && isTokensValid && isParametersValid && isInfoValid && isInitializePoolInputsValid; return { isParametersValid, isTypeValid, isInfoValid, isTokensValid, isPoolCreationInputValid, isValidTokenWeights }; }