diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration.tsx index c6fd9c8..2d83e31 100644 --- a/packages/nextjs/app/v3/_components/PoolConfiguration.tsx +++ b/packages/nextjs/app/v3/_components/PoolConfiguration.tsx @@ -9,7 +9,7 @@ import { TABS, type TabType, usePoolCreationStore, useValidatePoolCreationInput import { bgBeigeGradient } from "~~/utils"; export function PoolConfiguration() { - const { selectedTab, updatePool, step } = usePoolCreationStore(); + const { selectedTab, updatePool, createPoolTxHash } = usePoolCreationStore(); const { targetNetwork } = useTargetNetwork(); const [isPoolCreationModalOpen, setIsPoolCreationModalOpen] = useState(false); const { prev, next } = getAdjacentTabs(selectedTab); @@ -44,9 +44,10 @@ export function PoolConfiguration() { }; } + // Force modal to open if user has already sent "Deploy Pool" transaction (always step 1) useEffect(() => { - if (step > 1) setIsPoolCreationModalOpen(true); - }, [step]); + if (createPoolTxHash) setIsPoolCreationModalOpen(true); + }, [createPoolTxHash]); return ( <> diff --git a/packages/nextjs/hooks/v3/useBoostableWhitelist.ts b/packages/nextjs/hooks/v3/useBoostableWhitelist.ts index d1b55ed..85ea97a 100644 --- a/packages/nextjs/hooks/v3/useBoostableWhitelist.ts +++ b/packages/nextjs/hooks/v3/useBoostableWhitelist.ts @@ -68,8 +68,6 @@ export const useBoostableWhitelist = () => { const data = json.data.tokenGetTokens; - console.log("data", data); - // Create map of underlying token address to matching boosted variant info const boostableTokensMap = data.reduce((acc: Record
, token: Token) => { if (token.underlyingTokenAddress) acc[token.underlyingTokenAddress] = token; diff --git a/packages/nextjs/hooks/v3/useCreatePool.ts b/packages/nextjs/hooks/v3/useCreatePool.ts index 5f7ecfd..e4bdfec 100644 --- a/packages/nextjs/hooks/v3/useCreatePool.ts +++ b/packages/nextjs/hooks/v3/useCreatePool.ts @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import { CreatePool, CreatePoolV3BaseInput, @@ -10,7 +11,7 @@ import { import { useMutation } from "@tanstack/react-query"; import { parseEventLogs, parseUnits, zeroAddress } from "viem"; import { usePublicClient, useWalletClient } from "wagmi"; -import { useTransactor } from "~~/hooks/scaffold-eth"; +// import { useTransactor } from "~~/hooks/scaffold-eth"; import { useBoostableWhitelist, usePoolCreationStore } from "~~/hooks/v3"; const poolFactoryAbi = { @@ -24,7 +25,8 @@ const TOKEN_WEIGHT_DECIMALS = 16; export const useCreatePool = () => { const { data: walletClient } = useWalletClient(); const publicClient = usePublicClient(); - const writeTx = useTransactor(); + // const writeTx = useTransactor(); + const { tokenConfigs, name, @@ -38,8 +40,34 @@ export const useCreatePool = () => { disableUnbalancedLiquidity, amplificationParameter, updatePool, + createPoolTxHash, + step, } = usePoolCreationStore(); + const { data: boostableWhitelist } = useBoostableWhitelist(); + + // If user disconnects during pending tx state, this will look up tx receipt based on tx hash saved in local storage immediately after tx is sent (i.e. right after button is clicked) + useEffect(() => { + async function getTxReceipt() { + if (!publicClient || !createPoolTxHash || poolType === undefined || step !== 1) return; + + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: createPoolTxHash }); + + const logs = parseEventLogs({ + abi: poolFactoryAbi[poolType], + logs: txReceipt.logs, + }); + + if (logs.length > 0 && "args" in logs[0] && "pool" in logs[0].args) { + const newPool = logs[0].args.pool; + updatePool({ poolAddress: newPool, step: 2 }); + } else { + throw new Error("Expected pool address not found in event logs"); + } + } + getTxReceipt(); + }, [createPoolTxHash, publicClient, poolType, updatePool, step]); + function createPoolInput(poolType: PoolType): CreatePoolV3StableInput | CreatePoolV3WeightedInput { if (poolType === undefined) throw new Error("No pool type provided!"); if (!publicClient) throw new Error("Public client must be available!"); @@ -88,30 +116,26 @@ export const useCreatePool = () => { const input = createPoolInput(poolType); const call = createPool.buildCall(input); - const hash = await writeTx( - () => - walletClient.sendTransaction({ - account: walletClient.account, - data: call.callData, - to: call.to, - }), - { - blockConfirmations: 1, - onBlockConfirmation: () => { - console.log("Successfully deployed and registered a balancer v3 pool!"); - }, - }, - ); + // Not using transactor here because we need to immediately save tx hash to local storage for zen dragon edge case + // He sends transactions with low gas limit which means they stay pending for hours + const hash = await walletClient.sendTransaction({ + account: walletClient.account, + data: call.callData, + to: call.to, + }); + if (!hash) throw new Error("Failed to generate pool creation transaction hash"); + + updatePool({ createPoolTxHash: hash }); - if (!hash) throw new Error("No pool creation transaction hash"); - const txReceipt = await publicClient.getTransactionReceipt({ hash }); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash }); const logs = parseEventLogs({ abi: poolFactoryAbi[poolType], logs: txReceipt.logs, }); + if (logs.length > 0 && "args" in logs[0] && "pool" in logs[0].args) { const newPool = logs[0].args.pool; - updatePool({ poolAddress: newPool, createPoolTxHash: hash, step: 2 }); + updatePool({ poolAddress: newPool, step: 2 }); } else { throw new Error("Expected pool address not found in event logs"); } diff --git a/packages/nextjs/hooks/v3/usePoolCreationStore.ts b/packages/nextjs/hooks/v3/usePoolCreationStore.ts index 8878c3d..94c45f8 100644 --- a/packages/nextjs/hooks/v3/usePoolCreationStore.ts +++ b/packages/nextjs/hooks/v3/usePoolCreationStore.ts @@ -45,9 +45,9 @@ export interface PoolCreationStore { disableUnbalancedLiquidity: boolean; enableDonation: boolean; amplificationParameter: string; - createPoolTxHash: string | undefined; - swapTxHash: string | undefined; - initPoolTxHash: string | undefined; + createPoolTxHash: `0x${string}` | undefined; + swapTxHash: `0x${string}` | undefined; + initPoolTxHash: `0x${string}` | undefined; updatePool: (updates: Partial