Skip to content

Commit

Permalink
restyle pool actions tab and query subgraph for all pools
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPereira committed Mar 17, 2024
1 parent f3531ed commit cc5c8d5
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 146 deletions.
136 changes: 97 additions & 39 deletions packages/nextjs/app/pools/_components/PoolActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,41 @@
import { Fragment, useState } from "react";
import { ChevronDownIcon } from "@heroicons/react/24/outline";

type Action = "Swap" | "Join" | "Exit";

/**
* Allow user to perform swap, join, and exit transactions with a pool
*/
export const PoolActions = () => {
const [selectedTab, setSelectedTab] = useState("swap");
const [activeTab, setActiveTab] = useState<Action>("Swap");

const tabs = {
Swap: <SwapTab />,
Join: <JoinTab />,
Exit: <ExitTab />,
};

return (
<div className="w-full">
<h5 className="text-2xl font-bold mb-3">Actions</h5>
<div role="tablist" className="tabs tabs-lifted">
<input
type="radio"
name="swap_tab"
role="tab"
className="tab"
aria-label="Swap"
checked={selectedTab === "swap"}
onChange={() => setSelectedTab("swap")}
/>
<div role="tabpanel" className="tab-content bg-base-200 border-base-300 rounded-box p-6">
<SwapTab />
</div>

<input
type="radio"
name="join_tab"
role="tab"
className="tab"
aria-label="Join"
checked={selectedTab === "join"}
onChange={() => setSelectedTab("join")}
/>
<div role="tabpanel" className="tab-content bg-base-200 border-base-300 rounded-box p-6">
Add liquidity to the pool
</div>

<input
type="radio"
name="exit_tab"
role="tab"
className="tab"
aria-label="Exit"
checked={selectedTab === "exit"}
onChange={() => setSelectedTab("exit")}
/>
<div role="tabpanel" className="tab-content bg-base-200 border-base-300 rounded-box p-6">
Remove liquidity from the pool
<div className="w-full bg-base-200 rounded-xl">
<div className="flex border-b border-accent">
{Object.keys(tabs).map(tab => (
<button
key={tab}
onClick={() => setActiveTab(tab as Action)}
className={`py-3 flex-1 ${
activeTab === tab
? "bg-base-100 rounded-tl-lg rounded-tr-lg font-bold"
: "border-b-4 border-transparent"
} focus:outline-none`}
>
{tab}
</button>
))}
</div>
<div className="p-5">{tabs[activeTab]}</div>
</div>
</div>
);
Expand Down Expand Up @@ -102,7 +89,78 @@ const SwapTab = () => {
</div>
</div>
<div>
<button className="btn btn-accent mt-3 w-full rounded-lg">Swap</button>
<button className="btn btn-accent mt-3 w-full rounded-lg">Query Swap</button>
</div>
</Fragment>
);
};

const JoinTab = () => {
return (
<Fragment>
<div className="mb-5">
<div>
<label>Tokens In</label>
</div>
<div className="relative">
<input type="number" className="text-2xl w-full input input-bordered rounded-lg bg-base-200 p-10" />
<div className="dropdown dropdown-end absolute top-3 right-4 ">
<div tabIndex={0} role="button" className="btn m-1 btn-accent rounded-lg w-24">
DAI <ChevronDownIcon className="w-4 h-4" />
</div>
<ul tabIndex={0} className="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
<li>
<a>Item 1</a>
</li>
<li>
<a>Item 2</a>
</li>
</ul>
</div>
</div>
</div>
<div className="mb-5">
<div className="relative">
<input type="number" className="text-2xl w-full input input-bordered rounded-lg bg-base-200 p-10" />
<div className="dropdown dropdown-end absolute top-3 right-4 ">
<div tabIndex={0} role="button" className="btn m-1 btn-accent rounded-lg w-24">
USDe <ChevronDownIcon className="w-4 h-4" />
</div>
<ul tabIndex={0} className="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
<li>
<a>Item 1</a>
</li>
<li>
<a>Item 2</a>
</li>
</ul>
</div>
</div>
</div>
<div>
<button className="btn btn-accent mt-3 w-full rounded-lg">Query Join</button>
</div>
</Fragment>
);
};

const ExitTab = () => {
return (
<Fragment>
<div className="mb-5">
<div>
<label>BPT In</label>
</div>
<div className="relative">
<input type="number" className="text-2xl w-full input input-bordered rounded-lg bg-base-200 p-10" />

<div tabIndex={0} role="button" className="btn m-1 btn-accent rounded-lg absolute top-3 right-4">
B-50DAI-50USDe
</div>
</div>
</div>
<div>
<button className="btn btn-accent mt-3 w-full rounded-lg">Query Join</button>
</div>
</Fragment>
);
Expand Down
8 changes: 3 additions & 5 deletions packages/nextjs/app/pools/_components/PoolComposition.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { SkeletonLoader } from "~~/components/common";

/**
* Display a pool's token composition including the tokens' address, balance, and weight
*/
export const PoolComposition = () => {
return (
<div className="w-full">
<div className="w-full flex flex-col">
<h5 className="text-2xl font-bold mb-3">Composition</h5>
<SkeletonLoader />
</div>
);
};

const SkeletonLoader = () => {
return <div className="animate-pulse bg-base-200 rounded-xl w-full h-72"></div>;
};
165 changes: 85 additions & 80 deletions packages/nextjs/app/pools/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import type { NextPage } from "next";
import { type Address, isAddress } from "viem";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import deployedContractsData from "~~/contracts/deployedContracts";
import { usePoolContract } from "~~/hooks/balancer";
import scaffoldConfig from "~~/scaffold.config";

const Pools: NextPage = () => {
const [poolAddress, setPoolAddress] = useState<Address>("");
const [isDropdownOpen, setIsDropdownOpen] = useState(false);

const isValidAddress = isAddress(poolAddress);

Expand All @@ -20,94 +22,97 @@ const Pools: NextPage = () => {
}));

const [selectedPool, setSelectedPool] = useState<Address>(scaffoldPools[0].address);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);

return (
<div className="bg-base-300 flex-grow">
<div className="flex items-center flex-col flex-grow py-10 px-5 md:px-10 xl:px-20">
<div className="pb-10 border-b border-white">
<h1 className="text-3xl md:text-5xl font-bold my-10">🌊 Pools</h1>
<p className="text-xl my-0">
Balancer is infinitely extensible to allow for any conceivable pool type with custom curves, logic,
parameters, and more. Each pool deployed to balancer is its own smart contract. This tool allows you to
interact with any pool currently deployed (custom or existing). To get started, select one of your custom
pools deployed through scaffold eth or enter the contract address of the desired pool below.
</p>
</div>
const { data: pool } = usePoolContract(selectedPool);

<section className="flex justify-center flex-wrap gap-5 w-full mb-5 items-center text-xl border-b border-white py-5">
<div className={`dropdown dropdown-end ${isDropdownOpen ? "dropdown-open" : ""}`}>
<div
tabIndex={0}
role="button"
className="btn text-lg btn-accent w-96"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
>
Choose Custom Pool
</div>
<ul
tabIndex={0}
className={`dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52 mt-3 ${
!isDropdownOpen ? "hidden" : ""
}`}
>
{scaffoldPools.map(pool => (
<li key={pool.name}>
<button
onClick={() => {
setSelectedPool(pool.address);
setIsDropdownOpen(false); // Close the dropdown
}}
>
{pool.name}
</button>
</li>
))}
</ul>
return (
<div className="flex-grow bg-base-300">
<div className="max-w-screen-2xl mx-auto">
<div className="flex items-center flex-col flex-grow py-10 px-5 md:px-10 xl:px-20">
<div className="pb-10">
<h1 className="text-3xl md:text-5xl font-bold my-10">🌊 Pools</h1>
<p className="text-xl my-0">
Balancer is infinitely extensible to allow for any conceivable pool type with custom curves, logic,
parameters, and more. Each pool deployed to balancer is its own smart contract. This tool allows you to
interact with any pool currently deployed (custom or existing). To get started, select one of your custom
pools deployed through scaffold eth or enter the contract address of the desired pool below.
</p>
</div>
<div>OR</div>
<form
className="flex flex-row items-center gap-2"
onSubmit={event => {
event.preventDefault();
setSelectedPool(poolAddress);
setPoolAddress("");
}}
>
<div className="relative">
<input
value={poolAddress}
onChange={e => setPoolAddress(e.target.value)}
className="input input-bordered bg-base-200 w-96 text-center pr-16"
placeholder="Search by contract addresss"
/>
<button
className="btn btn-sm btn-accent absolute top-2 right-3 "
type="submit"
disabled={!isValidAddress}

<section className="flex justify-center flex-wrap gap-5 w-full mb-5 items-center text-xl py-5 border-b border-t border-accent">
<div className={`dropdown dropdown-end ${isDropdownOpen ? "dropdown-open" : ""}`}>
<div
tabIndex={0}
role="button"
className="btn text-lg btn-accent w-96 font-normal"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
>
Choose custom pool
</div>
<ul
tabIndex={0}
className={`dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52 mt-3 ${
!isDropdownOpen ? "hidden" : ""
}`}
>
<MagnifyingGlassIcon className="h-5 w-5" />
</button>
{scaffoldPools.map(pool => (
<li key={pool.name}>
<button
onClick={() => {
setSelectedPool(pool.address);
setIsDropdownOpen(false); // Close the dropdown
}}
>
{pool.name}
</button>
</li>
))}
</ul>
</div>
</form>
</section>
<div>OR</div>
<form
className="flex flex-row items-center gap-2"
onSubmit={event => {
event.preventDefault();
setSelectedPool(poolAddress);
setPoolAddress("");
}}
>
<div className="relative">
<input
value={poolAddress}
onChange={e => setPoolAddress(e.target.value)}
className="input input-bordered bg-base-200 w-96 text-center pr-16"
placeholder="Search by contract addresss"
/>
<button
className="btn btn-sm btn-accent absolute top-2 right-3 "
type="submit"
disabled={!isValidAddress}
>
<MagnifyingGlassIcon className="h-5 w-5" />
</button>
</div>
</form>
</section>

<div className="flex w-full mb-3 overflow-auto">
<h3 className="font-extrabold text-transparent text-3xl bg-clip-text bg-gradient-to-r from-pink-500 to-yellow-500">
{selectedPool}
</h3>
</div>
{selectedPool && (
<div className="w-full">
<div className="grid grid-cols-1 xl:grid-cols-2 w-full gap-10 mb-5">
<PoolDetails poolAddress={selectedPool} />
<PoolActions />
</div>
<div className="flex w-full mb-3 overflow-auto">
<h3 className="font-extrabold text-transparent text-3xl bg-clip-text bg-gradient-to-r from-pink-500 to-yellow-500">
{pool?.name}
</h3>
</div>
{selectedPool && (
<div className="w-full">
<PoolComposition />
<div className="grid grid-cols-1 xl:grid-cols-2 w-full gap-10 mb-5">
<PoolComposition />
<PoolActions />
</div>
<div className="w-full">
<PoolDetails poolAddress={selectedPool} />
</div>
</div>
</div>
)}
)}
</div>
</div>
</div>
);
Expand Down
Loading

0 comments on commit cc5c8d5

Please sign in to comment.