Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 90 additions & 47 deletions apps/namadillo/src/App/Common/SelectAssetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,65 +36,108 @@ export const SelectAssetModal = ({

const [filter, setFilter] = useState("");

const filteredAssets = useMemo(() => {
return assets.filter(
const { assetsWithBalance, assetsWithoutBalance } = useMemo(() => {
const filtered = assets.filter(
(asset) =>
asset.name.toLowerCase().indexOf(filter.toLowerCase()) >= 0 ||
asset.symbol.toLowerCase().indexOf(filter.toLowerCase()) >= 0
);
}, [assets, filter]);

const withBalance: Asset[] = [];
const withoutBalance: Asset[] = [];

filtered.forEach((asset) => {
const tokenAddress =
ibcTransfer === "deposit" ? asset.base : (asset as NamadaAsset).address;

const balance = balances?.[tokenAddress];
const hasBalance = balance && balance[0].gt(0);

if (hasBalance) {
withBalance.push(asset);
} else {
withoutBalance.push(asset);
}
});

return {
assetsWithBalance: withBalance,
assetsWithoutBalance: withoutBalance,
};
}, [assets, filter, balances, ibcTransfer]);

const renderAssetItem = (asset: Asset): JSX.Element => {
// Fpr IbcTransfer(Deposits), we consider base denom as a token address.
const tokenAddress =
ibcTransfer === "deposit" ? asset.base : (asset as NamadaAsset).address;

const disabled =
!namTransfersEnabled && asset.address === nativeTokenAddress;

return (
<li key={asset.base} className="text-sm">
<button
onClick={() => {
onSelect(tokenAddress);
onClose();
}}
className={twMerge(
clsx(
"text-left px-4 py-2.5",
"w-full rounded-sm border border-transparent",
"hover:border-neutral-400 transition-colors duration-150",
{ "pointer-events-none opacity-50": disabled }
)
)}
disabled={disabled}
>
<TokenCard
asset={asset}
address={tokenAddress}
disabled={disabled}
balance={balances?.[tokenAddress]}
/>
</button>
</li>
);
};

const hasAnyAssets =
assetsWithBalance.length > 0 || assetsWithoutBalance.length > 0;

return (
<SelectModal title="Select Asset" onClose={onClose}>
<ConnectedWalletInfo walletAddress={walletAddress} />
<div className="my-4">
<Search placeholder="Search asset" onChange={setFilter} />
</div>
<Stack
as="ul"
gap={0}
className="max-h-[400px] overflow-auto dark-scrollbar pb-4 mr-[-0.5rem]"
>
{filteredAssets.map((asset) => {
// Fpr IbcTransfer(Deposits), we consider base denom as a token address.
const tokenAddress =
ibcTransfer === "deposit" ?
asset.base
: (asset as NamadaAsset).address;

const disabled =
!namTransfersEnabled && asset.address === nativeTokenAddress;
return (
<li key={asset.base} className="text-sm">
<button
onClick={() => {
onSelect(tokenAddress);
onClose();
}}
className={twMerge(
clsx(
"text-left px-4 py-2.5",
"w-full rounded-sm border border-transparent",
"hover:border-neutral-400 transition-colors duration-150",
{ "pointer-events-none opacity-50": disabled }
)
)}
disabled={disabled}
>
<TokenCard
asset={asset}
address={tokenAddress}
disabled={disabled}
balance={balances?.[tokenAddress]}
/>
</button>
</li>
);
})}
{filteredAssets.length === 0 && (
<p className="py-2 font-light">There are no available assets</p>
<div className="max-h-[400px] overflow-auto dark-scrollbar pb-4 mr-[-0.5rem]">
{assetsWithBalance.length > 0 && (
<>
<h3 className="text-xs font-medium text-neutral-500 px-4 py-2 uppercase tracking-wide">
Your tokens
</h3>
<Stack as="ul" gap={0}>
{assetsWithBalance.map(renderAssetItem)}
</Stack>
</>
)}

{assetsWithoutBalance.length > 0 && (
<>
<h3 className="text-xs font-medium text-neutral-500 px-4 py-2 mt-4 uppercase tracking-wide">
All tokens
</h3>
<Stack as="ul" gap={0}>
{assetsWithoutBalance.map(renderAssetItem)}
</Stack>
</>
)}
</Stack>

{!hasAnyAssets && (
<p className="py-2 px-4 font-light">There are no available assets</p>
)}
</div>
</SelectModal>
);
};
44 changes: 21 additions & 23 deletions apps/namadillo/src/App/Common/SelectedAsset.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SkeletonLoading, Tooltip } from "@namada/components";
import { SkeletonLoading } from "@namada/components";
import { EmptyResourceIcon } from "App/Transfer/EmptyResourceIcon";
import clsx from "clsx";
import { getAssetImageUrl } from "integrations/utils";
Expand All @@ -8,13 +8,15 @@ import { Asset } from "types";
type SelectedAssetProps = {
asset?: Asset;
isLoading?: boolean;
imageSize?: "small" | "large";
isDisabled?: boolean;
onClick?: () => void;
};

export const SelectedAsset = ({
asset,
isLoading,
imageSize = "small",
isDisabled,
onClick,
}: SelectedAssetProps): JSX.Element => {
Expand Down Expand Up @@ -53,29 +55,25 @@ export const SelectedAsset = ({
</span>
)}
{asset && (
<div className="relative group/tooltip">
<Tooltip position="top" className="z-50">
{asset.address}
</Tooltip>
<span className={selectorClassList}>
<img
className={clsx(
"w-8 aspect-square object-cover select-none",
"object-center bg-neutral-800 rounded-full"
)}
alt={`${asset.name} image`}
src={getAssetImageUrl(asset)}
/>
<span className="flex items-center gap-1 text-md">
{asset.symbol}
{!isDisabled && (
<i className="text-sm">
<GoChevronDown />
</i>
)}
</span>
<span className={selectorClassList}>
<img
className={clsx(
imageSize === "small" ? "w-8" : "w-16",
"aspect-square object-cover select-none",
"object-center bg-neutral-800 rounded-full"
)}
alt={`${asset.name} image`}
src={getAssetImageUrl(asset)}
/>
<span className="flex items-center gap-1 text-md">
{asset.symbol}
{!isDisabled && (
<i className="text-sm">
<GoChevronDown />
</i>
)}
</span>
</div>
</span>
)}
</button>
);
Expand Down
6 changes: 0 additions & 6 deletions apps/namadillo/src/App/Swap/SwapHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { SwapIcon } from "App/Icons/SwapIcon";

export const SwapHeader = (): JSX.Element => {
return (
<header className="flex flex-col items-center text-center mb-8 gap-5">
<h1 className="text-yellow"> Shielded Swaps </h1>
<i className="flex items-center justify-center w-13 text-yellow mx-auto relative z-10">
<SwapIcon />
</i>
<p>Swap an asset you hold in the shield pool</p>
</header>
);
};
4 changes: 4 additions & 0 deletions apps/namadillo/src/App/Swap/SwapModule.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Panel } from "@namada/components";
import { MaspSyncCover } from "App/Common/MaspSyncCover";
import { useRequiresNewShieldedSync } from "hooks/useRequiresNewShieldedSync";
import { useAtomValue } from "jotai";
import { Link } from "react-router-dom";
import { swapStatusAtom } from "./state/atoms";
Expand All @@ -12,6 +14,7 @@ import { SwapSuccess } from "./SwapSuccess";
// and pass the shared state(accounts, fees, etc.) as props to the module components
export const SwapModule = (): JSX.Element => {
const status = useAtomValue(swapStatusAtom);
const requiresNewShieldedSync = useRequiresNewShieldedSync();

return (
<Panel className="relative rounded-sm flex flex-col flex-1 pt-9">
Expand Down Expand Up @@ -44,6 +47,7 @@ export const SwapModule = (): JSX.Element => {
</p>
)}
</section>
{requiresNewShieldedSync && <MaspSyncCover />}
</Panel>
);
};
1 change: 1 addition & 0 deletions apps/namadillo/src/App/Swap/SwapSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const SwapSource = ({
{!isSubmitting && (
<div className="grid grid-cols-[max-content_auto] gap-5 mb-3">
<SelectedAsset
imageSize="large"
asset={asset}
isLoading={isLoadingAssets}
onClick={openAssetSelector}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,19 @@ export const LocalStorageTransactionCard = ({
<h4 className="text-neutral-400">To</h4>
<div className="flex items-center justify-between">
<h4
className={isShieldedAddress(receiver ?? "") ? "text-yellow" : ""}
className={
(
isShieldedAddress(receiver ?? "") ||
transaction.type === "ShieldedOsmosisSwap"
) ?
"text-yellow"
: ""
}
>
{isShieldedAddress(receiver ?? "") ?
{(
isShieldedAddress(receiver ?? "") ||
transaction.type === "ShieldedOsmosisSwap"
) ?
<span className="flex items-center gap-1">
<FaLock className="w-4 h-4" /> Shielded
</span>
Expand Down