diff --git a/README.md b/README.md
index 3e46610..b19c3b8 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,8 @@ yarn start
## Run on Fork
+> ⚠️ **Note:** Fork development is only supported for CoW AMMs
+
1. Add the following ENV vars to a `.env` file located in the root directory
```
diff --git a/packages/nextjs/app/v3/_components/ChooseToken.tsx b/packages/nextjs/app/v3/_components/ChooseToken.tsx
index 1be7a14..570c82b 100644
--- a/packages/nextjs/app/v3/_components/ChooseToken.tsx
+++ b/packages/nextjs/app/v3/_components/ChooseToken.tsx
@@ -341,8 +341,8 @@ const BoostOpportunityModal = ({
Boosted tokens provide your liquidity pool with a layer of sustainable yield. If you select{" "}
-
{boostedVariant.symbol} , all
{standardVariant.symbol} in this pool will be supplied to
- Aave's lending market to earn additional yield.
+
{boostedVariant.symbol} , all
{standardVariant.symbol} in this pool will be supplied to earn
+ additional yield.
Note that if you choose the boosted variant, the necessary rate provider address will be auto-filled for you
diff --git a/packages/nextjs/app/v3/_components/PoolConfiguration.tsx b/packages/nextjs/app/v3/_components/PoolConfiguration.tsx
index 2d83e31..cd34aa9 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, createPoolTxHash } = usePoolCreationStore();
+ const { selectedTab, updatePool, createPoolTx } = usePoolCreationStore();
const { targetNetwork } = useTargetNetwork();
const [isPoolCreationModalOpen, setIsPoolCreationModalOpen] = useState(false);
const { prev, next } = getAdjacentTabs(selectedTab);
@@ -44,10 +44,10 @@ export function PoolConfiguration() {
};
}
- // Force modal to open if user has already sent "Deploy Pool" transaction (always step 1)
+ // Force modal to open if user has already sent "Deploy Pool" transaction (which is step 1)
useEffect(() => {
- if (createPoolTxHash) setIsPoolCreationModalOpen(true);
- }, [createPoolTxHash]);
+ if (createPoolTx.wagmiHash || createPoolTx.safeHash) setIsPoolCreationModalOpen(true);
+ }, [createPoolTx.wagmiHash, createPoolTx.safeHash]);
return (
<>
diff --git a/packages/nextjs/app/v3/_components/PoolCreationManager.tsx b/packages/nextjs/app/v3/_components/PoolCreationManager.tsx
index c6ab0a4..03ec815 100644
--- a/packages/nextjs/app/v3/_components/PoolCreationManager.tsx
+++ b/packages/nextjs/app/v3/_components/PoolCreationManager.tsx
@@ -11,11 +11,13 @@ import {
import {
useBoostableWhitelist,
useCreatePool,
+ useCreatePoolTxHash,
useInitializePool,
+ useInitializePoolTxHash,
useMultiSwap,
+ useMultiSwapTxHash,
usePoolCreationStore,
useUserDataStore,
- useWaitForTransactionReceipt,
} from "~~/hooks/v3/";
import { bgBeigeGradient, bgBeigeGradientHover, bgPrimaryGradient } from "~~/utils";
import { getBlockExplorerTxLink } from "~~/utils/scaffold-eth";
@@ -24,30 +26,36 @@ 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 PoolCreationManager({ setIsModalOpen }: { setIsModalOpen: (isOpen: boolean) => void }) {
- const { step, tokenConfigs, clearPoolStore, createPoolTxHash, swapTxHash, initPoolTxHash, chain } =
+ const { step, tokenConfigs, clearPoolStore, createPoolTx, swapToBoostedTx, initPoolTx, chain } =
usePoolCreationStore();
const { clearUserData } = useUserDataStore();
const { data: boostableWhitelist } = useBoostableWhitelist();
const { mutate: createPool, isPending: isCreatePoolPending, error: createPoolError } = useCreatePool();
+ const { isFetching: isFetchPoolAddressPending, error: fetchPoolAddressError } = useCreatePoolTxHash();
+
const { mutate: multiSwap, isPending: isMultiSwapPending, error: multiSwapError } = useMultiSwap();
- const {
- mutate: initializePool,
- isPending: isInitializePoolPending,
- error: initializePoolError,
- } = useInitializePool();
- const { isLoadingTxReceipt } = useWaitForTransactionReceipt(); // Fetches tx from tx hash if user disconnects during pending tx state
+ const { isFetching: isMultiSwapTxHashPending, error: multiSwapTxHashError } = useMultiSwapTxHash();
+
+ const { mutate: initPool, isPending: isInitPoolPending, error: initPoolError } = useInitializePool();
+ const { isFetching: isInitPoolTxHashPending, error: initPoolTxHashError } = useInitializePoolTxHash();
- const poolDeploymentUrl = createPoolTxHash ? getBlockExplorerTxLink(chain?.id, createPoolTxHash) : undefined;
- const poolInitializationUrl = initPoolTxHash ? getBlockExplorerTxLink(chain?.id, initPoolTxHash) : undefined;
- const multiSwapUrl = swapTxHash ? getBlockExplorerTxLink(chain?.id, swapTxHash) : undefined;
+ const poolDeploymentUrl = createPoolTx.wagmiHash
+ ? getBlockExplorerTxLink(chain?.id, createPoolTx.wagmiHash)
+ : undefined;
+ const multiSwapUrl = swapToBoostedTx.wagmiHash
+ ? getBlockExplorerTxLink(chain?.id, swapToBoostedTx.wagmiHash)
+ : undefined;
+ const poolInitializationUrl = initPoolTx.wagmiHash
+ ? getBlockExplorerTxLink(chain?.id, initPoolTx.wagmiHash)
+ : undefined;
const deployStep = createTransactionStep({
label: "Deploy Pool",
blockExplorerUrl: poolDeploymentUrl,
onSubmit: createPool,
- isPending: isCreatePoolPending || isLoadingTxReceipt,
- error: createPoolError,
+ isPending: isCreatePoolPending || isFetchPoolAddressPending,
+ error: createPoolError || fetchPoolAddressError,
});
const approveOnTokenSteps = tokenConfigs.map((token, idx) => {
@@ -56,7 +64,7 @@ export function PoolCreationManager({ setIsModalOpen }: { setIsModalOpen: (isOpe
if (!symbol || !decimals)
return {
label: "Token Approval",
- component:
Invalid token configuration. Missing symbol or decimals. ,
+ component:
Missing token info! ,
};
return {
@@ -71,8 +79,8 @@ export function PoolCreationManager({ setIsModalOpen }: { setIsModalOpen: (isOpe
createTransactionStep({
label: "Swap to Boosted",
onSubmit: multiSwap,
- isPending: isMultiSwapPending,
- error: multiSwapError,
+ isPending: isMultiSwapPending || isMultiSwapTxHashPending,
+ error: multiSwapError || multiSwapTxHashError,
blockExplorerUrl: multiSwapUrl,
}),
);
@@ -102,9 +110,9 @@ export function PoolCreationManager({ setIsModalOpen }: { setIsModalOpen: (isOpe
const initializeStep = createTransactionStep({
label: "Initialize Pool",
- onSubmit: initializePool,
- isPending: isInitializePoolPending || isLoadingTxReceipt,
- error: initializePoolError,
+ onSubmit: initPool,
+ isPending: isInitPoolPending || isInitPoolTxHashPending,
+ error: initPoolError || initPoolTxHashError,
blockExplorerUrl: poolInitializationUrl,
});
diff --git a/packages/nextjs/app/v3/page.tsx b/packages/nextjs/app/v3/page.tsx
index 5ee5c60..3fbddf4 100644
--- a/packages/nextjs/app/v3/page.tsx
+++ b/packages/nextjs/app/v3/page.tsx
@@ -6,19 +6,13 @@ import { PoolConfiguration, PoolDetails } from "./_components";
import type { NextPage } from "next";
import { ArrowUpRightIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { BalancerLogo } from "~~/components/assets/BalancerLogo";
-import { Alert, ContactSupportModal, PoolStateResetModal, SafeWalletAlert } from "~~/components/common";
-import { useIsSafeWallet } from "~~/hooks/safe";
+import { Alert, ContactSupportModal, PoolStateResetModal } from "~~/components/common";
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
import { usePoolCreationStore, useUserDataStore, useValidateNetwork } from "~~/hooks/v3";
const BalancerV3: NextPage = () => {
- const { isWrongNetwork, isWalletConnected } = useValidateNetwork();
const { clearPoolStore, chain } = usePoolCreationStore();
const { clearUserData } = useUserDataStore();
- const { targetNetwork: selectedNetwork } = useTargetNetwork();
- const [isInfoAlertVisible, setIsInfoAlertVisible] = useState(true);
-
- const isSafeWallet = useIsSafeWallet();
return (
@@ -29,121 +23,44 @@ const BalancerV3: NextPage = () => {
Balancer v3
- {!isWalletConnected ? (
-
-
-
-
- Please connect a wallet and switch to the network you wish to create a pool
-
-
-
-
-
- ) : isSafeWallet ? (
-
-
-
- ) : isWrongNetwork ? (
-
-
-
-
- You are connected to an unsupported network. To continue, please switch to Sepolia, Ethereum, or
- Gnosis
-
-
-
-
-
- ) : chain && selectedNetwork.id !== chain.id ? (
-
-
-
-
- You have already begun the pool configuration process. Please switch back to {chain.name}
-
-
-
-
-
- ) : (
- <>
- {!chain && (
-
-
-
-
- Make sure you switch to your desired network before beginning pool creation. You cannot switch
- after selecting pool type unless you reset progress
-
-
-
-
-
- )}
- {isInfoAlertVisible && (
-
-
-
-
- For tips and guidance on pool configuration and creation, check out our
-
- partner onboarding documentation
-
-
-
-
setIsInfoAlertVisible(false)}
- className="absolute top-3 right-3 p-1 rounded-full transition-colors text-neutral-700"
- >
-
-
-
-
- )}
+
-
-
+ <>
+
+
-
-
-
Pool Preview
- {chain && (
-
- {chain?.name}
-
- )}
-
-
-
-
-
·
-
{
- clearPoolStore();
- clearUserData();
- }}
- />
-
+
+
+
Pool Preview
+ {chain && (
+
+ {chain?.name}
+
+ )}
+
+
+
+
+
·
+
{
+ clearPoolStore();
+ clearUserData();
+ }}
+ />
+
-
-
- Pool creation not available on mobile
-
-
- >
- )}
+
+
+ Pool creation not available on mobile
+
+
+ >
@@ -151,3 +68,86 @@ const BalancerV3: NextPage = () => {
};
export default BalancerV3;
+
+function UserExperienceAlerts() {
+ const { targetNetwork: selectedNetwork } = useTargetNetwork();
+ const [isInfoAlertVisible, setIsInfoAlertVisible] = useState(true);
+ const { isWrongNetwork, isWalletConnected } = useValidateNetwork();
+ const { chain } = usePoolCreationStore();
+
+ return !isWalletConnected ? (
+