Skip to content

Commit

Permalink
Transaction history, Multihop & Expert mode togglers
Browse files Browse the repository at this point in the history
  • Loading branch information
lilchizh authored May 22, 2024
2 parents c328489 + 5a1c9f9 commit 5f42c09
Show file tree
Hide file tree
Showing 34 changed files with 650 additions and 293 deletions.
4 changes: 4 additions & 0 deletions src/assets/etherscan-logo-circle-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/etherscan-logo-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
78 changes: 61 additions & 17 deletions src/components/common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import { NavLink } from "react-router-dom"
import { useWeb3Modal, useWeb3ModalState } from "@web3modal/wagmi/react"
import { DEFAULT_CHAIN_ID, DEFAULT_CHAIN_NAME } from "@/constants/default-chain-id"
import { Button } from "@/components/ui/button"
import { UnplugIcon, WalletIcon } from "lucide-react"
import { AlignJustify, UnplugIcon, WalletIcon } from "lucide-react"
import Loader from "../Loader"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { useState } from "react"
import { Address } from "viem"
import { TransactionCard } from "../TransactionCard"
import { useAccount } from "wagmi"
import { usePendingTransactions, usePendingTransactionsStore } from "@/state/pendingTransactionsStore"

const Header = () => <header className="sticky top-4 z-10 grid grid-cols-3 justify-between items-center py-1 px-2 bg-card border border-card-border rounded-3xl gap-4">
<Algebra />
Expand All @@ -28,6 +35,14 @@ const Account = () => {

const { open } = useWeb3Modal()

const { pendingTransactions } = usePendingTransactionsStore()

const { address: account } = useAccount();

const showTxHistory = account && pendingTransactions[account] ? Object.keys(pendingTransactions[account]).length > 0 : false

const pendingTxCount = account && pendingTransactions[account] ? Object.entries(pendingTransactions[account]).filter(([, transaction]) => transaction.loading).length : 0;

const { selectedNetworkId } = useWeb3ModalState()

if (selectedNetworkId !== DEFAULT_CHAIN_ID) return <div className="flex justify-end">
Expand All @@ -41,33 +56,62 @@ const Account = () => {
</Button>
</div>

return <div className="flex justify-end gap-4 pt-[2px] whitespace-nowrap">
return <div className="flex h-full justify-end gap-4 whitespace-nowrap">
<div className="hidden lg:block">
<w3m-network-button />
</div>
<div className="hidden md:block">
<w3m-button />
</div>
<div className="hidden md:block">
<w3m-button balance={pendingTxCount > 0 ? "hide" : "show"} />
</div>
<div className="md:hidden">
<Button onClick={() => open()} variant={'icon'} size={'icon'}>
<WalletIcon />
</Button>
</div>
{
showTxHistory &&
<TransactionHistoryPopover>
{
pendingTxCount > 0 ?
<Button
className="flex font-normal items-center my-auto h-10 px-3 justify-center gap-2 cursor-pointer hover:bg-primary-button/80 border border-card bg-primary-button rounded-3xl transition-all duration-200"
aria-label="Transaction history"
>
<Loader />
<span>{pendingTxCount}</span>
<span>Pending</span>
</Button>
:
<Button
variant="ghost"
className="flex font-normal items-center my-auto h-10 px-3 justify-center gap-2 bg-card-light/20 cursor-pointer border border-card-light hover:border-border/30 rounded-3xl transition-all duration-200"
aria-label="Transaction history"
>
<AlignJustify size={20} />
</Button>
}
</TransactionHistoryPopover>
}
</div>
}

// const Transactions = () => {
const TransactionHistoryPopover = ({children}: {children: React.ReactNode}) => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const pendingTransactions = usePendingTransactions();
const { address: account } = useAccount();

// const [pendingTransactions, setPendingTransactions] = useState<OnTransactionsParameter>([])

// useWatchPendingTransactions({
// listener: (hashes) => setPendingTransactions(hashes)
// })

// return <Avatar className="w-[35px] h-[35px]">
// <AvatarFallback>{pendingTransactions.length}</AvatarFallback>
// </Avatar>

// }
if (account) return <Popover open={isOpen} onOpenChange={setIsOpen}>
<PopoverTrigger>
{children}
</PopoverTrigger>
<PopoverContent className="w-fit max-h-80 flex flex-col gap-4 -translate-x-28 translate-y-2 max-xl:-translate-x-8 max-xs:-translate-x-4" sideOffset={6}>
Transaction History
<hr/>
<ul className="flex flex-col gap-4 w-64 overflow-auto ">
{Object.entries(pendingTransactions[account]).reverse().map(([hash, transaction]) => <TransactionCard key={hash} hash={hash as Address} transaction={transaction} />)}
</ul>
</PopoverContent>
</Popover>
}

export default Header
4 changes: 3 additions & 1 deletion src/components/common/Loader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { cn } from "@/lib/utils";
import { Loader2Icon } from "lucide-react";

interface LoaderProps {
size?: number;
color?: string;
className?: string;
}

const Loader = ({ size = 22, color = 'white' }: LoaderProps) => <Loader2Icon size={size} color={color} className="animate-spin" />
const Loader = ({ size = 22, color = 'white', className }: LoaderProps) => <Loader2Icon size={size} color={color} className={cn("animate-spin", className)} />

export default Loader
21 changes: 18 additions & 3 deletions src/components/common/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ const Settings = () => {
<SettingsIcon />
</Button>
</PopoverTrigger>
<PopoverContent align={'end'} className="flex flex-col gap-4 w-fit bg-card rounded-3xl border border-card-border text-white">
<PopoverContent align={'end'} className="flex flex-col gap-4 p-6 w-fit bg-card rounded-3xl border border-card-border text-white">
<div className="text-md font-bold">Transaction Settings</div>
<Separator orientation={'horizontal'} className="bg-border" />
<SlippageTolerance />
<TransactionDeadline />
<Multihop />
<ExpertMode />
</PopoverContent>
</Popover>
Expand Down Expand Up @@ -156,13 +157,27 @@ const ExpertMode = () => {

return <div className="flex flex-col gap-2 max-w-[332px]">
<div className="flex justify-between items-center gap-2 text-md font-semibold">
Expert Mode
<Switch checked={isExpertMode} onCheckedChange={setIsExpertMode} />
<label htmlFor="expert-mode">Expert mode</label>
<Switch id="expert-mode" checked={isExpertMode} onCheckedChange={setIsExpertMode} />
</div>
<p className="whitespace-break-spaces">
Advanced control over swap parameters such as price setting and gas management.
</p>
</div>
}

const Multihop = () => {
const { isMultihop, actions: { setIsMultihop } } = useUserState();

return <div className="flex flex-col gap-2 max-w-[332px]">
<div className="flex justify-between items-center gap-2 text-md font-semibold">
<label htmlFor="multihop">Multihop</label>
<Switch id="multihop" checked={isMultihop} onCheckedChange={setIsMultihop} />
</div>
<p className="whitespace-break-spaces">
Optimized trades across multiple liquidity pools.
</p>
</div>
}

export default Settings;
9 changes: 6 additions & 3 deletions src/components/common/Table/poolsColumns.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ColumnDef } from '@tanstack/react-table';
import { HeaderItem } from './common';
import { Address } from 'wagmi';
import { useCurrency } from '@/hooks/common/useCurrency';
import CurrencyLogo from '../CurrencyLogo';
import { TokenFieldsFragment } from '@/graphql/generated/graphql';
import { DynamicFeePluginIcon } from '../PluginIcons';
import { formatUSD } from '@/utils/common/formatUSD';
import { usePoolPlugins } from '@/hooks/pools/usePoolPlugins';
import { Skeleton } from '@/components/ui/skeleton';
import { FarmingPluginIcon } from '../PluginIcons';
import { useCurrency } from '@/hooks/common/useCurrency';

interface Pair {
token0: TokenFieldsFragment;
Expand All @@ -26,8 +26,11 @@ interface Pool {
}

const PoolPair = ({ pair, fee }: Pool) => {
const currencyA = useCurrency(pair.token0.id as Address);
const currencyB = useCurrency(pair.token1.id as Address);
const token0 = pair.token0.id as Address;
const token1 = pair.token1.id as Address;

const currencyA = useCurrency(token0, true);
const currencyB = useCurrency(token1, true);

return (
<div className="flex items-center gap-4 ml-2">
Expand Down
62 changes: 62 additions & 0 deletions src/components/common/TransactionCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useCurrency } from "@/hooks/common/useCurrency";
import { truncateHash } from "@/utils/common/truncateHash";
import { Address } from "viem";
import CurrencyLogo from "../CurrencyLogo";
import EtherScanLogo from "@/assets/etherscan-logo-circle.svg"
import { Check, ExternalLinkIcon, X } from "lucide-react";
import { Link } from "react-router-dom";
import { Transaction, TransactionType } from "@/state/pendingTransactionsStore";
import Loader from "../Loader";
import { FarmingPositionImg } from "@/components/farming/FarmingPositionImg";

export const TransactionCard = ({ hash, transaction }: { hash: Address, transaction: Transaction }) => {
const currencyA = useCurrency(transaction.data.tokenA, true);
const currencyB = useCurrency(transaction.data.tokenB, true);

const txType = transaction.data.type;

return <Link
to={`https://holesky.etherscan.io/tx/${hash}`}
target={'_blank'}
>
<li className="flex group h-16 justify-between items-center gap-4 w-full bg-card-dark rounded-3xl p-4 border border-border/60 hover:border-border hover:bg-card-dark/60 transition-all duration-200" key={hash}>
{
txType === TransactionType.FARM && transaction.data.tokenId ?
<FarmingPositionImg positionId={BigInt(transaction.data.tokenId)} size={10} />
:

currencyB && currencyA ?
<div className="w-[36px] relative">
<CurrencyLogo className="absolute bottom-0 translate-y-1/4" currency={currencyA} size={28} />
<CurrencyLogo className="absolute top-0 left-3 -translate-y-1/4" currency={currencyB} size={28} />
</div>
:
currencyA ?
<CurrencyLogo currency={currencyA} size={40} />
:
<img className="brightness-150" src={EtherScanLogo} width={40} height={40} />

}
<div className="flex flex-col mr-auto">
<span className="text-xs opacity-60">{transaction.data.title}</span>
{
currencyB && currencyA ?
<span className="text-sm">{currencyA.symbol} / {currencyB.symbol}</span>
:
currencyA ?
<span className="text-sm">{currencyA.symbol}</span>
:
<span>{truncateHash(hash as Address)}</span>
}
</div>
{
transaction.loading ? <Loader className="group-hover:hidden" size={20} />
:
transaction.success ? <Check className="text-blue-300 group-hover:hidden" size={18} />
:
transaction.error && <X className="text-red-500 group-hover:hidden" size={18} />
}
<ExternalLinkIcon className="hidden group-hover:block" size={18} />
</li>
</Link>
}
13 changes: 9 additions & 4 deletions src/components/create-pool/CreatePoolForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import {
computePoolAddress,
} from '@cryptoalgebra/integral-sdk';
import { usePrepareAlgebraPositionManagerMulticall } from '@/generated';
import { useTransitionAwait } from '@/hooks/common/useTransactionAwait';
import { useTransactionAwait } from '@/hooks/common/useTransactionAwait';
import { Address, useContractWrite } from 'wagmi';
import { useDerivedMintInfo, useMintState } from '@/state/mintStore';
import Loader from '@/components/common/Loader';
import { PoolState, usePool } from '@/hooks/pools/usePool';
import Summary from '../Summary';
import SelectPair from '../SelectPair';
import { STABLECOINS } from '@/constants/tokens';
import { TransactionType } from '@/state/pendingTransactionsStore';

const CreatePoolForm = () => {
const { currencies } = useDerivedSwapInfo();
Expand Down Expand Up @@ -77,10 +78,14 @@ const CreatePoolForm = () => {
const { data: createPoolData, write: createPool } =
useContractWrite(createPoolConfig);

const { isLoading } = useTransitionAwait(
const { isLoading } = useTransactionAwait(
createPoolData?.hash,
'Create Pool',
'',
{
title: 'Create Pool',
tokenA: currencyA?.wrapped.address as Address,
tokenB: currencyB?.wrapped.address as Address,
type: TransactionType.POOL,
},
'/pools'
);

Expand Down
13 changes: 9 additions & 4 deletions src/components/create-position/AddLiquidityButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
} from '@/constants/default-chain-id';
import { usePrepareAlgebraPositionManagerMulticall } from '@/generated';
import { useApprove } from '@/hooks/common/useApprove';
import { useTransitionAwait } from '@/hooks/common/useTransactionAwait';
import { useTransactionAwait } from '@/hooks/common/useTransactionAwait';
import { IDerivedMintInfo } from '@/state/mintStore';
import { TransactionType } from '@/state/pendingTransactionsStore';
import { useUserState } from '@/state/userStore';
import { ApprovalState } from '@/types/approve-state';
import {
Expand Down Expand Up @@ -118,10 +119,14 @@ export const AddLiquidityButton = ({
const { data: addLiquidityData, write: addLiquidity } =
useContractWrite(addLiquidityConfig);

const { isLoading: isAddingLiquidityLoading } = useTransitionAwait(
const { isLoading: isAddingLiquidityLoading } = useTransactionAwait(
addLiquidityData?.hash,
'Add liquidity',
'',
{
title: 'Add liquidity',
tokenA: baseCurrency?.wrapped.address as Address,
tokenB: quoteCurrency?.wrapped.address as Address,
type: TransactionType.POOL,
},
`/pool/${poolAddress}`
);

Expand Down
Loading

0 comments on commit 5f42c09

Please sign in to comment.