Skip to content

Commit

Permalink
chore(tangle-dapp): Selector Modals, Bridge UI cleanup & Remove Sygma…
Browse files Browse the repository at this point in the history
… Bridge (#2596)

Co-authored-by: Pavan Soratur <[email protected]>
  • Loading branch information
devpavan04 and Pavan Soratur authored Oct 23, 2024
1 parent 34ae4ab commit 066d0ae
Show file tree
Hide file tree
Showing 44 changed files with 1,035 additions and 1,467 deletions.
156 changes: 106 additions & 50 deletions apps/tangle-dapp/app/bridge/AmountAndTokenInput.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
'use client';

import { DropdownMenuTrigger as DropdownTrigger } from '@radix-ui/react-dropdown-menu';
import { TokenIcon } from '@webb-tools/icons/TokenIcon';
import { Modal, ModalContent, useModal } from '@webb-tools/webb-ui-components';
import ChainOrTokenButton from '@webb-tools/webb-ui-components/components/buttons/ChainOrTokenButton';
import {
Dropdown,
DropdownBody,
DropdownMenuItem,
} from '@webb-tools/webb-ui-components/components/Dropdown';
import { ScrollArea } from '@webb-tools/webb-ui-components/components/ScrollArea';
import SkeletonLoader from '@webb-tools/webb-ui-components/components/SkeletonLoader';
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography';
import Decimal from 'decimal.js';
import { FC, useMemo } from 'react';
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { twMerge } from 'tailwind-merge';

import AmountInput from '../../components/AmountInput';
import { AssetConfig, AssetList } from '../../components/Lists/AssetList';
import { BRIDGE_SUPPORTED_TOKENS } from '../../constants/bridge';
import { useBridge } from '../../context/BridgeContext';
import useExplorerUrl from '../../hooks/useExplorerUrl';
import { BridgeTokenId } from '../../types/bridge';
import convertDecimalToBn from '../../utils/convertDecimalToBn';
import useBalance from './hooks/useBalance';
import { useTokenBalances } from './hooks/useBalance';
import useDecimals from './hooks/useDecimals';
import useSelectedToken from './hooks/useSelectedToken';
import useTypedChainId from './hooks/useTypedChainId';
Expand All @@ -32,34 +29,101 @@ const AmountAndTokenInput: FC = () => {
tokenIdOptions,
setIsAmountInputError,
isAmountInputError,
feeItems,
selectedSourceChain,
} = useBridge();
const selectedToken = useSelectedToken();
const { balance, isLoading } = useBalance();
const decimals = useDecimals();
const { sourceTypedChainId } = useTypedChainId();

const getExplorerUrl = useExplorerUrl();

const minAmount = useMemo(() => {
const existentialDeposit =
selectedToken.existentialDeposit[sourceTypedChainId];
const destChainTransactionFee =
selectedToken.destChainTransactionFee[sourceTypedChainId];

return (existentialDeposit ?? new Decimal(0))
.add(destChainTransactionFee ?? new Decimal(0))
.add(feeItems.sygmaBridge?.amount ?? new Decimal(0));
return (existentialDeposit ?? new Decimal(0)).add(
destChainTransactionFee ?? new Decimal(0),
);
}, [
selectedToken.existentialDeposit,
selectedToken.destChainTransactionFee,
sourceTypedChainId,
feeItems.sygmaBridge?.amount,
]);

const {
status: isTokenModalOpen,
open: openTokenModal,
close: closeTokenModal,
} = useModal(false);

const { getTokenBalance } = useTokenBalances();
const [tokenBalances, setTokenBalances] = useState<
Record<string, Decimal | null>
>({});

const fetchBalances = useCallback(async () => {
const balances: Record<string, Decimal | null> = {};
for (const tokenId of tokenIdOptions) {
const token = BRIDGE_SUPPORTED_TOKENS[tokenId];
const erc20TokenContractAddress =
token.erc20TokenContractAddress?.[sourceTypedChainId];
balances[tokenId] = await getTokenBalance(
erc20TokenContractAddress ?? '0x0',
token.decimals[sourceTypedChainId] ?? 18,
);
}
setTokenBalances(balances);
}, [tokenIdOptions, getTokenBalance, sourceTypedChainId]);

useEffect(() => {
fetchBalances();
}, [fetchBalances]);

const assets: AssetConfig[] = useMemo(() => {
return tokenIdOptions.map((tokenId) => {
const token = BRIDGE_SUPPORTED_TOKENS[tokenId];
const erc20TokenContractAddress =
token.erc20TokenContractAddress?.[sourceTypedChainId];
const selectedChainExplorerUrl =
selectedSourceChain.blockExplorers?.default;
const explorerUrl = getExplorerUrl(
erc20TokenContractAddress ?? '0x0',
'address',
'web3',
selectedChainExplorerUrl?.url,
false,
);
return {
symbol: token.symbol,
balance: tokenBalances[tokenId] ?? new Decimal(0),
explorerUrl: explorerUrl?.toString(),
};
});
}, [
tokenIdOptions,
sourceTypedChainId,
selectedSourceChain.blockExplorers?.default,
getExplorerUrl,
tokenBalances,
]);

const onSelectAsset = (asset: AssetConfig) => {
setSelectedTokenId(asset.symbol as BridgeTokenId);
closeTokenModal();
};

const selectedAssetBalance = useMemo(() => {
return tokenBalances[selectedToken.id] ?? new Decimal(0);
}, [tokenBalances, selectedToken.id]);

return (
<div className="relative">
<div
className={twMerge(
'w-full flex items-center gap-2 bg-mono-20 dark:bg-mono-160 rounded-lg pr-4',
'w-full flex items-center gap-2 bg-mono-20 dark:bg-mono-170 rounded-lg pr-4',
isAmountInputError && 'border border-red-70 dark:border-red-50',
)}
>
Expand All @@ -83,39 +147,15 @@ const AmountAndTokenInput: FC = () => {
}
errorMessageClassName="absolute left-0 bottom-[-24px] !text-[14px] !leading-[21px]"
/>
<Dropdown>
<DropdownTrigger asChild>
<ChainOrTokenButton
value={selectedToken.symbol}
status="success"
className={twMerge(
'w-[130px] border-0 px-3 bg-[#EFF3F6] dark:bg-mono-140',
'hover:bg-[#EFF3F6] dark:hover:bg-mono-140',
)}
iconType="token"
/>
</DropdownTrigger>
<DropdownBody className="border-0 w-[119px] min-w-fit mr-[11px]">
<ScrollArea className="max-h-[300px] w-[130px]">
<ul>
{tokenIdOptions.map((tokenId) => {
const token = BRIDGE_SUPPORTED_TOKENS[tokenId];
return (
<li key={tokenId}>
<DropdownMenuItem
leftIcon={<TokenIcon size="lg" name={token.symbol} />}
onSelect={() => setSelectedTokenId(tokenId)}
className="px-3 normal-case"
>
{token.symbol}
</DropdownMenuItem>
</li>
);
})}
</ul>
</ScrollArea>
</DropdownBody>
</Dropdown>

{/* Token Selector */}
<ChainOrTokenButton
value={selectedToken.symbol}
iconType="token"
onClick={openTokenModal}
className="w-[130px] border-0 px-3 bg-mono-40 dark:bg-mono-140"
status="success"
/>
</div>

{isLoading ? (
Expand All @@ -129,11 +169,27 @@ const AmountAndTokenInput: FC = () => {
className="absolute right-0 bottom-[-24px] text-mono-120 dark:text-mono-100"
>
Balance:{' '}
{balance !== null
? `${balance.toString()} ${selectedToken.symbol}`
{selectedAssetBalance !== null
? `${selectedAssetBalance.toString()} ${selectedToken.symbol}`
: 'N/A'}
</Typography>
)}

<Modal>
{/* Token Selector Modal */}
<ModalContent
isCenter
isOpen={isTokenModalOpen}
onInteractOutside={closeTokenModal}
className="w-[500px] h-[600px]"
>
<AssetList
onClose={closeTokenModal}
assets={assets}
onSelectAsset={onSelectAsset}
/>
</ModalContent>
</Modal>
</div>
);
};
Expand Down
49 changes: 39 additions & 10 deletions apps/tangle-dapp/app/bridge/BridgeConfirmationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Typography,
useWebbUI,
} from '@webb-tools/webb-ui-components';
import { shortenHex } from '@webb-tools/webb-ui-components/utils/shortenHex';
import { FC, useCallback } from 'react';

import { useBridge } from '../../context/BridgeContext';
Expand Down Expand Up @@ -122,7 +123,6 @@ const BridgeConfirmationModal: FC<BridgeConfirmationModalProps> = ({
handleClose(); // TODO: handle clear form
}}
isDisabled={
feeItems.sygmaBridge?.isLoading ||
feeItems.hyperlaneInterchain?.isLoading ||
feeItems.gas?.isLoading ||
feeItems.gas?.amount === null ||
Expand Down Expand Up @@ -150,33 +150,62 @@ const ConfirmationItem: FC<{
tokenName: string;
}> = ({ type, chainName, accAddress, amount, tokenName }) => {
return (
<div className="bg-mono-20 dark:bg-mono-160 w-full space-y-2 p-4 rounded-xl">
<div className="bg-mono-20 dark:bg-mono-170 w-full space-y-2 p-4 rounded-xl">
<div className="flex justify-between items-center">
<Typography variant="body1">
<Typography
variant="body1"
className="text-mono-120 dark:text-mono-120"
fw="bold"
>
{type === 'source' ? 'From' : 'To'}
</Typography>
<div className="flex items-center gap-1.5">
<ChainIcon name={chainName} />
<Typography variant="body1">{chainName}</Typography>
<Typography
variant="body1"
className="text-mono-200 dark:text-mono-0"
>
{chainName}
</Typography>
</div>
</div>
<div className="flex justify-between items-center">
<Typography variant="body1">Account</Typography>
<Typography
variant="body1"
className="max-w-[65%] break-words text-right"
fw="bold"
className="text-mono-120 dark:text-mono-120"
>
{accAddress}
Account
</Typography>
<Typography
variant="body1"
className="max-w-[65%] break-words text-right text-mono-200 dark:text-mono-0"
>
{shortenHex(accAddress, 10)}
</Typography>
</div>
<div className="flex justify-between items-center">
<Typography variant="body1">Amount</Typography>
<Typography
variant="body1"
fw="bold"
className="text-mono-120 dark:text-mono-120"
>
Amount
</Typography>
<div className="flex items-center gap-1.5">
<Typography variant="body1" fw="bold">
<Typography
variant="body1"
className="text-mono-200 dark:text-mono-0"
>
{amount}
</Typography>
<TokenIcon name={tokenName} />
<Typography variant="body1">{tokenName}</Typography>
<Typography
variant="body1"
className="text-mono-200 dark:text-mono-0"
>
{tokenName}
</Typography>
</div>
</div>
</div>
Expand Down
17 changes: 5 additions & 12 deletions apps/tangle-dapp/app/bridge/BridgeContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,10 @@ const BridgeContainer: FC<BridgeContainerProps> = ({ className }) => {
} = useBridge();
const activeAccountAddress = useActiveAccountAddress();
const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false);
const {
buttonAction,
buttonText,
buttonLoadingText,
isLoading,
isDisabled,
// errorMessage,
} = useActionButton({
handleOpenConfirmModal: () => setIsConfirmModalOpen(true),
});
const { buttonAction, buttonText, buttonLoadingText, isLoading, isDisabled } =
useActionButton({
handleOpenConfirmModal: () => setIsConfirmModalOpen(true),
});

const hideFeeDetails = useMemo(
() =>
Expand All @@ -61,8 +55,7 @@ const BridgeContainer: FC<BridgeContainerProps> = ({ className }) => {
<>
<div
className={twMerge(
'max-w-[640px] min-h-[580px] bg-mono-0 dark:bg-mono-190 p-5 md:p-8',
'rounded-xl border border-mono-40 dark:border-mono-160',
'max-w-[640px] min-h-[580px] bg-mono-0 dark:bg-mono-190 p-5 md:p-8 rounded-xl',
'shadow-webb-lg dark:shadow-webb-lg-dark',
'flex flex-col',
className,
Expand Down
Loading

0 comments on commit 066d0ae

Please sign in to comment.