Skip to content

Commit

Permalink
feat(tangle-dapp): Create table listing liquid staking pools (#2536)
Browse files Browse the repository at this point in the history
  • Loading branch information
yurixander authored Sep 20, 2024
1 parent 04b45af commit cc6b042
Show file tree
Hide file tree
Showing 70 changed files with 1,382 additions and 427 deletions.
17 changes: 16 additions & 1 deletion apps/tangle-dapp/app/liquid-staking/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import LsStakeCard from '../../components/LiquidStaking/stakeAndUnstake/LsStakeC
import LsUnstakeCard from '../../components/LiquidStaking/stakeAndUnstake/LsUnstakeCard';
import UnstakeRequestsTable from '../../components/LiquidStaking/unstakeRequestsTable/UnstakeRequestsTable';
import { LsSearchParamKey } from '../../constants/liquidStaking/types';
import LsPoolsTable from '../../containers/LsPoolsTable';
import { useLsStore } from '../../data/liquidStaking/useLsStore';
import useSearchParamState from '../../hooks/useSearchParamState';
import isLsParachainChainId from '../../utils/liquidStaking/isLsParachainChainId';
import TabListItem from '../restake/TabListItem';
import TabsList from '../restake/TabsList';

Expand All @@ -25,6 +28,10 @@ const LiquidStakingTokenPage: FC = () => {
value ? SearchParamAction.STAKE : SearchParamAction.UNSTAKE,
});

const { selectedProtocolId } = useLsStore();

const isParachainChain = isLsParachainChainId(selectedProtocolId);

return (
<div className="flex flex-wrap gap-12">
<div className="flex flex-col gap-4 w-full min-w-[450px] max-w-[600px]">
Expand All @@ -45,7 +52,15 @@ const LiquidStakingTokenPage: FC = () => {
</div>

<div className="flex flex-col flex-grow w-min gap-4 min-w-[370px]">
{isStaking ? <LsValidatorTable /> : <UnstakeRequestsTable />}
{isStaking ? (
isParachainChain ? (
<LsPoolsTable />
) : (
<LsValidatorTable />
)
) : (
<UnstakeRequestsTable />
)}
</div>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions apps/tangle-dapp/components/LiquidStaking/AddressLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { ExternalLinkLine } from '@webb-tools/icons';
import { shortenString, Typography } from '@webb-tools/webb-ui-components';
import { FC, useCallback } from 'react';

import { AnySubstrateAddress } from '../../types/utils';
import { SubstrateAddress } from '../../types/utils';

export type AddressLinkProps = {
address: AnySubstrateAddress | HexString;
address: SubstrateAddress | HexString;
};

const AddressLink: FC<AddressLinkProps> = ({ address }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,22 @@ import {
LiquidStakingItem,
LiquidStakingItemType,
} from '../../types/liquidStaking';
import pluralize from '../../utils/pluralize';

const DEFAULT_PAGINATION: PaginationState = {
pageIndex: 0,
pageSize: 10,
};

const SELECTED_ITEMS_COLUMN_SORT = {
// TODO: Need to update the correct id. It seems that the `id` field no longer exists in the row's type. Need to statically-type-link-it instead of hard coding it, to avoid the same bug in the future.
id: 'id',
desc: false,
} as const satisfies ColumnSort;

export const LsValidatorTable = () => {
const { selectedProtocolId, setSelectedItems } = useLsStore();
const { selectedProtocolId, setSelectedNetworkEntities: setSelectedItems } =
useLsStore();
const { isLoading, data, dataType } = useLsValidators(selectedProtocolId);
const [searchValue, setSearchValue] = useState('');
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
Expand Down Expand Up @@ -185,7 +188,7 @@ export const LsValidatorTable = () => {
<Input
id="ls-validator-selection-search"
rightIcon={<Search className="mr-2" />}
placeholder="Search"
placeholder={`Search ${tableTitle.toLowerCase()}...`}
value={searchValue}
onChange={(newSearchValue) => setSearchValue(newSearchValue)}
className="mb-1"
Expand Down Expand Up @@ -215,7 +218,7 @@ export const LsValidatorTable = () => {
canNextPage={table.getCanNextPage()}
nextPage={table.nextPage}
setPageIndex={table.setPageIndex}
title={itemText + 's'}
title={pluralize(itemText.toLowerCase(), data.length > 1)}
className="!px-0 !py-0 !pt-6"
/>
)}
Expand Down
136 changes: 0 additions & 136 deletions apps/tangle-dapp/components/LiquidStaking/StakedAssetsTable.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { FC } from 'react';
import { twMerge } from 'tailwind-merge';

export type SkeletonLoaderSetProps = {
rowCount: number;
rowCount?: number;
className?: string;
};

const TableRowsSkeleton: FC<SkeletonLoaderSetProps> = ({
rowCount,
rowCount = 10,
className,
}) => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { twMerge } from 'tailwind-merge';
import useVaults from '../../app/liquid-staking/useVaults';
import StatItem from '../../components/StatItem';
import TableCellWrapper from '../../components/tables/TableCellWrapper';
import { PagePath } from '../../types';
import { Asset, Vault } from '../../types/liquidStaking';
import LsTokenIcon from '../LsTokenIcon';

Expand Down Expand Up @@ -80,8 +81,7 @@ const vaultColumns = [
cell: ({ row }) => (
<TableCellWrapper removeBorder>
<div className="flex items-center justify-end flex-1 gap-2">
{/* TODO: add proper href */}
<Link href="#" passHref>
<Link href={PagePath.LIQUID_STAKING} passHref>
<Button
variant="utility"
className="uppercase body4"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { FC, useMemo } from 'react';
import { LsProtocolId } from '../../../constants/liquidStaking/types';
import formatBn from '../../../utils/formatBn';
import getLsProtocolDef from '../../../utils/liquidStaking/getLsProtocolDef';
import scaleAmountByPermill from '../../../utils/scaleAmountByPermill';
import scaleAmountByPercentage from '../../../utils/scaleAmountByPercentage';
import DetailItem from './DetailItem';
import useLsFeePermill from './useLsFeePermill';
import useLsFeePercentage from './useLsFeePercentage';

export type FeeDetailItemProps = {
isMinting: boolean;
Expand All @@ -19,20 +19,18 @@ const FeeDetailItem: FC<FeeDetailItemProps> = ({
inputAmount,
protocolId,
}) => {
const feePermill = useLsFeePermill(protocolId, isMinting);
const feePercentage = useLsFeePercentage(protocolId, isMinting);

const protocol = getLsProtocolDef(protocolId);

// TODO: Add liquifier fees, and select either parachain or liquifier fees based on the given protocol's id.

const feeAmount = useMemo(() => {
// Propagate error or loading state.
if (typeof feePermill !== 'number') {
return feePermill;
if (typeof feePercentage !== 'number') {
return feePercentage;
}

return scaleAmountByPermill(inputAmount ?? BN_ZERO, feePermill);
}, [feePermill, inputAmount]);
return scaleAmountByPercentage(inputAmount ?? BN_ZERO, feePercentage);
}, [feePercentage, inputAmount]);

const formattedFeeAmount = useMemo(() => {
// Propagate error or loading state.
Expand All @@ -48,9 +46,9 @@ const FeeDetailItem: FC<FeeDetailItemProps> = ({
}, [feeAmount, protocol.decimals, protocol.token]);

const feeTitle =
typeof feePermill !== 'number'
typeof feePercentage !== 'number'
? 'Fee'
: `Fee (${(feePermill * 100).toFixed(2)}%)`;
: `Fee (${(feePercentage * 100).toFixed(2)}%)`;

return <DetailItem title={feeTitle} value={formattedFeeAmount} />;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ import { Alert } from '@webb-tools/webb-ui-components';
import { FC } from 'react';

import { LsProtocolId } from '../../../constants/liquidStaking/types';
import useLsFeePermill from './useLsFeePermill';
import useLsFeePercentage from './useLsFeePercentage';

// 10%.
const THRESHOLD_PERMILL = 0.1;
const THRESHOLD_PERCENTAGE = 0.1;

export type LsFeeWarningProps = {
isMinting: boolean;
selectedProtocolId: LsProtocolId;
};

const LsFeeWarning: FC<LsFeeWarningProps> = ({ selectedProtocolId }) => {
const fee = useLsFeePermill(selectedProtocolId, true);
const fee = useLsFeePercentage(selectedProtocolId, true);

return (
typeof fee === 'number' &&
fee >= THRESHOLD_PERMILL && (
fee >= THRESHOLD_PERCENTAGE && (
<Alert
type="warning"
title="High fees"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const LsStakeCard: FC = () => {

const selectedProtocol = getLsProtocolDef(selectedProtocolId);

// TODO: Not loading the correct protocol for: '?amount=123000000000000000000&protocol=7&network=1&action=stake'. When network=1, it switches to protocol=5 on load. Could this be because the protocol is reset to its default once the network is switched?
useSearchParamSync({
key: LsSearchParamKey.PROTOCOL_ID,
value: selectedProtocolId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
} from '@webb-tools/webb-ui-components';
import { FC, useEffect, useMemo } from 'react';

import { AnySubstrateAddress } from '../../../types/utils';
import { SubstrateAddress } from '../../../types/utils';
import formatBn from '../../../utils/formatBn';
import LsTokenIcon from '../../LsTokenIcon';
import AddressLink from '../AddressLink';

export type SelectTokenModalProps = {
isOpen: boolean;
options: Omit<TokenListItemProps, 'onClick'>[];
onTokenSelect: (address: AnySubstrateAddress) => void;
onTokenSelect: (address: SubstrateAddress) => void;
onClose: () => void;
};

Expand All @@ -28,7 +28,7 @@ const SelectTokenModal: FC<SelectTokenModalProps> = ({
}) => {
// Sanity check: Ensure all addresses are unique.
useEffect(() => {
const seenAddresses = new Set<AnySubstrateAddress>();
const seenAddresses = new Set<SubstrateAddress>();

for (const option of options) {
if (seenAddresses.has(option.address)) {
Expand Down Expand Up @@ -81,7 +81,7 @@ const SelectTokenModal: FC<SelectTokenModalProps> = ({
};

export type TokenListItemProps = {
address: AnySubstrateAddress;
address: SubstrateAddress;
decimals: number;
amount: BN;
onClick: () => void;
Expand Down
Loading

0 comments on commit cc6b042

Please sign in to comment.