Skip to content

Commit

Permalink
feat(tangle-dapp): Include LSTs in table
Browse files Browse the repository at this point in the history
  • Loading branch information
yurixander committed Dec 14, 2024
1 parent 89c5afe commit 8c11644
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
Typography,
} from '@webb-tools/webb-ui-components';
import { TableVariant } from '@webb-tools/webb-ui-components/components/Table/types';
import { FC, useMemo, useState } from 'react';
import { FC, useCallback, useMemo, useState } from 'react';

import LsTokenIcon from '../components/LsTokenIcon';
import StatItem from '../components/StatItem';
Expand All @@ -39,10 +39,18 @@ import { TableStatus } from '../components';
import useRestakeRewardConfig from '../data/restake/useRestakeRewardConfig';
import useRestakeDelegatorInfo from '../data/restake/useRestakeDelegatorInfo';
import useIsAccountConnected from '../hooks/useIsAccountConnected';

export type RestakeBalanceRow = {
name: string;
token: string;
import useLsPools from '../data/liquidStaking/useLsPools';
import { TANGLE_TOKEN_DECIMALS } from '@webb-tools/dapp-config';

enum RowType {
ASSET,
LS_POOL,
}

type Row = {
type: RowType;
name?: string;
tokenSymbol: string;
tvl: BN;
tvlInUsd?: number;
available: BN;
Expand All @@ -55,31 +63,35 @@ export type RestakeBalanceRow = {
apyFractional?: number;
};

const COLUMN_HELPER = createColumnHelper<RestakeBalanceRow>();
const COLUMN_HELPER = createColumnHelper<Row>();

const COLUMNS = [
COLUMN_HELPER.accessor('name', {
COLUMN_HELPER.accessor('tokenSymbol', {
header: () => 'Asset',
sortDescFirst: true,
sortingFn: sortByLocaleCompare((row) => row.name),
cell: (props) => (
sortingFn: sortByLocaleCompare((row) => row.name ?? row.tokenSymbol),
cell: (props) => {
const name = props.row.original.name;

<TableCellWrapper className="pl-3">
<div className="flex items-center gap-2">
<LsTokenIcon name={props.row.original.iconName} size="lg" />

<Typography variant="h5" className="whitespace-nowrap">
{props.getValue()}
</Typography>
{name !== undefined && (
<Typography variant="h5" className="whitespace-nowrap">
{name}
</Typography>
)}

<Typography
variant="body1"
className="whitespace-nowrap dark:text-mono-100"
>
{props.row.original.token}
{props.getValue()}
</Typography>
</div>
</TableCellWrapper>
),
</TableCellWrapper>;
},
}),
COLUMN_HELPER.accessor('available', {
header: () => 'Available',
Expand All @@ -98,7 +110,7 @@ const COLUMNS = [
return (
<TableCellWrapper>
<StatItem
title={`${formattedMyStake} ${props.row.original.token}`}
title={`${formattedMyStake} ${props.row.original.tokenSymbol}`}
subtitle={subtitle}
removeBorder
/>
Expand All @@ -123,7 +135,7 @@ const COLUMNS = [
return (
<TableCellWrapper>
<StatItem
title={`${formattedMyStake} ${props.row.original.token}`}
title={`${formattedMyStake} ${props.row.original.tokenSymbol}`}
subtitle={subtitle}
removeBorder
/>
Expand All @@ -150,7 +162,7 @@ const COLUMNS = [
return (
<TableCellWrapper>
<StatItem
title={`${formattedTvl} ${props.row.original.token}`}
title={`${formattedTvl} ${props.row.original.tokenSymbol}`}
subtitle={subtitle}
removeBorder
/>
Expand Down Expand Up @@ -236,27 +248,21 @@ const COLUMNS = [
}),
];

const RestakeBalancesTable: FC = () => {
const AssetsAndBalancesTable: FC = () => {
const [sorting, setSorting] = useState<SortingState>([]);
const { balances } = useRestakeBalances();
const { assetMap } = useRestakeAssetMap();
const { rewardConfig } = useRestakeRewardConfig();
const { delegatorInfo } = useRestakeDelegatorInfo();
const allPools = useLsPools();
const isAccountConnected = useIsAccountConnected();

const restakeBalanceRows = useMemo<RestakeBalanceRow[]>(() => {
return Object.entries(balances).flatMap(([assetId, balance]) => {
const assetDetails: (typeof assetMap)[string] | undefined =
assetMap[assetId];

if (assetDetails === undefined) {
return [];
}

const getTotalLockedInAsset = useCallback(
(assetId: number) => {
const deposited = delegatorInfo?.deposits[assetId].amount;

const delegated = delegatorInfo?.delegations.find((delegation) => {
return delegation.assetId === assetId;
return delegation.assetId === assetId.toString();
});

const depositedBn =
Expand All @@ -267,34 +273,66 @@ const RestakeBalancesTable: FC = () => {
? BN_ZERO
: new BN(delegated.amountBonded.toString());

return depositedBn.add(delegatedBn);
},
[delegatorInfo?.delegations, delegatorInfo?.deposits],
);

const assetRows = useMemo<Row[]>(() => {
return Object.entries(balances).flatMap(([assetId, balance]) => {
const assetDetails: (typeof assetMap)[string] | undefined =
assetMap[assetId];

if (assetDetails === undefined) {
return [];
}

return {
type: RowType.ASSET,
name: assetDetails.name,
// TODO: Calculate by issuance of asset.
tvl: BN_ZERO,
available: new BN(balance.balance.toString()),
// TODO: Calculate by deposit amount in restaking of asset.
locked: delegatedBn.add(depositedBn),
locked: getTotalLockedInAsset(parseInt(assetId)),
// TODO: This won't work because reward config is PER VAULT not PER ASSET. But isn't each asset its own vault?
apyFractional: rewardConfig.configs[assetId]?.apy,
token: assetDetails.symbol,
tokenSymbol: assetDetails.symbol,
iconName: 'tnt',
decimals: assetDetails.decimals,
} as RestakeBalanceRow;
} satisfies Row;
});
}, [
assetMap,
balances,
delegatorInfo?.delegations,
delegatorInfo?.deposits,
rewardConfig.configs,
]);

const rows = useMemo<RestakeBalanceRow[]>(() => {
}, [assetMap, balances, getTotalLockedInAsset, rewardConfig.configs]);

const lsPoolRows = useMemo<Row[]>(() => {
if (!(allPools instanceof Map)) {
return [];
}

const pools = Array.from(allPools.values());

return pools.map((pool) => {
const tokenSymbol = `${pool.name ?? 'Pool'}#${pool.id}`.toUpperCase();

return {
type: RowType.LS_POOL,
tokenSymbol,
tvl: pool.totalStaked,
// TODO: Should be 'my stake'.
available: pool.totalStaked,
locked: getTotalLockedInAsset(pool.id),
iconName: 'tnt',
decimals: TANGLE_TOKEN_DECIMALS,
apyFractional: pool.apyPercentage,
} satisfies Row;
});
}, [allPools, getTotalLockedInAsset]);

const rows = useMemo<Row[]>(() => {
// Sort by highest available balance (descending).
return [...restakeBalanceRows].sort((a, b) => {
return [...assetRows, ...lsPoolRows].sort((a, b) => {
return b.available.cmp(a.available);
});
}, [restakeBalanceRows]);
}, [assetRows, lsPoolRows]);

const table = useReactTable({
data: rows,
Expand Down Expand Up @@ -330,4 +368,4 @@ const RestakeBalancesTable: FC = () => {
return <Table variant={TableVariant.GLASS_OUTER} tableProps={table} />;
};

export default RestakeBalancesTable;
export default AssetsAndBalancesTable;
4 changes: 2 additions & 2 deletions apps/tangle-dapp/src/pages/account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Typography } from '@webb-tools/webb-ui-components/typography/Typography
import { FC } from 'react';

import AccountSummaryCard from '../components/account/AccountSummaryCard';
import RestakeBalancesTable from '../containers/RestakeBalancesTable';
import AssetsAndBalancesTable from '../containers/AssetsAndBalancesTable';
import PointsReminder from '../components/account/PointsReminder';

const AccountPage: FC = () => {
Expand All @@ -18,7 +18,7 @@ const AccountPage: FC = () => {
Assets &amp; Balances
</Typography>

<RestakeBalancesTable />
<AssetsAndBalancesTable />
</div>
);
};
Expand Down
2 changes: 0 additions & 2 deletions apps/tangle-dapp/src/pages/liquid-staking/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ const LiquidStakingPage: FC = () => {
setIsStakingInStore(isStaking);
}, [isStaking, setIsStakingInStore]);

// Sync the URL param state of whether liquid staking or unstaking with
// the Zustand store state.
useEffect(() => {
setIsStaking(isStakingInStore);
}, [isStakingInStore, setIsStaking]);
Expand Down

0 comments on commit 8c11644

Please sign in to comment.