Skip to content

Commit

Permalink
Sort markets by supplied USD value (#488)
Browse files Browse the repository at this point in the history
Co-authored-by: oskarvu <[email protected]>
  • Loading branch information
yivlad and oskarvu authored Dec 12, 2024
1 parent 1cc1624 commit eac3a74
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Token } from '@/domain/types/Token'
import { TokenCell } from '@/features/savings/components/stablecoins-in-wallet/components/TokenCell'
import { Button } from '@/ui/atoms/button/Button'
import { Panel } from '@/ui/atoms/panel/Panel'
import { DataTable, DataTableProps } from '@/ui/molecules/data-table/DataTable'
import { DataTable, DataTableColumnDefinitions } from '@/ui/molecules/data-table/DataTable'
import { useMemo } from 'react'

export interface TokensToDepositProps {
Expand All @@ -12,7 +12,7 @@ export interface TokensToDepositProps {
}

export function TokensToDeposit({ assets, openStakeDialog }: TokensToDepositProps) {
const columnDef: DataTableProps<TokenWithBalance>['columnDef'] = useMemo(
const columnDef: DataTableColumnDefinitions<TokenWithBalance> = useMemo(
() => ({
token: {
header: 'Token',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function MarketsTable({ entries, chainId, hideTableHeader, 'data-testid':
hideTableHeader={hideTableHeader}
data={entries}
data-testid={dataTestId}
defaultSortingState={[{ id: 'totalSupplied', desc: true }]}
columnDefinition={{
asset: {
header: 'Assets',
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/features/markets/logic/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getChainConfigEntry } from '@/config/chain'
import { getAirdropsData } from '@/config/chain/utils/airdrops'
import { paths } from '@/config/paths'
import { sortByUsdValue } from '@/domain/common/sorters'
import { MarketInfo, Reserve } from '@/domain/market-info/marketInfo'
import { RowClickOptions } from '@/ui/molecules/data-table/DataTable'
import { Transformer, TransformerResult, applyTransformers } from '@/utils/applyTransformers'
Expand All @@ -25,6 +26,7 @@ export function transformReserves(marketInfo: MarketInfo): MarketEntry[] {
return applyTransformers(marketInfo.chainId, r, marketInfo.reserves)(transformers)
})
.filter((r): r is MarketEntryRowData => r !== null)
.sort((a, b) => -sortByUsdValue(a, b, 'totalSupplied')) // this is needed for mobile view where we don't have sorting functions
}

function skipInactiveReserves(_: number, reserve: Reserve): undefined | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { savingsDepositDialogConfig } from '@/features/dialogs/savings/deposit/S
import { assets as uiAssets } from '@/ui/assets'
import { Button } from '@/ui/atoms/button/Button'
import { Panel } from '@/ui/atoms/panel/Panel'
import { DataTable, DataTableProps } from '@/ui/molecules/data-table/DataTable'
import { DataTable, DataTableColumnDefinitions } from '@/ui/molecules/data-table/DataTable'
import { cn } from '@/ui/utils/style'
import { testIds } from '@/ui/utils/testIds'
import { useMemo } from 'react'
Expand All @@ -26,7 +26,7 @@ export function StablecoinsInWallet({
showConvertDialogButton,
migrationInfo,
}: StablecoinsInWalletProps) {
const columnDef: DataTableProps<AssetInWallet>['columnDef'] = useMemo(
const columnDef: DataTableColumnDefinitions<AssetInWallet> = useMemo(
() => ({
token: {
header: 'Token',
Expand Down
164 changes: 82 additions & 82 deletions packages/app/src/pages/Markets.test-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,72 +33,52 @@ test.describe('Markets', () => {
await marketsPage.expectActiveMarketsTable([
{
asset: {
name: 'DAI Stablecoin',
symbol: 'DAI',
name: 'Lido Staked ETH',
symbol: 'wstETH',
},
totalSupplied: {
tokenAmount: '962.8M',
usdValue: '$962.8M',
tokenAmount: '519K',
usdValue: '$2.06B',
},
depositAPY: {
// @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests
value: '8.52%',
value: '<0.01%',
},
totalBorrowed: {
tokenAmount: '913.6M',
usdValue: '$913.6M',
tokenAmount: '51.56',
usdValue: '$204.7K',
},
borrowAPY: {
value: '9.00%',
hasAirDrop: true,
},
status: {
// @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests
supply: 'Can be supplied',
collateral: 'Cannot be used as collateral',
borrow: 'Can be borrowed',
},
},
{
asset: {
name: 'Savings Dai',
symbol: 'sDAI',
},
totalSupplied: {
tokenAmount: '13.49M',
usdValue: '$14.73M',
},
depositAPY: {
value: '0.00%',
value: '0.25%',
},
totalBorrowed: undefined,
borrowAPY: undefined,
status: {
supply: 'Can be supplied',
collateral: 'Can be used as collateral',
borrow: 'Cannot be borrowed',
borrow: 'Can be borrowed',
},
},
{
asset: {
name: 'Circle USD',
symbol: 'USDC',
name: 'DAI Stablecoin',
symbol: 'DAI',
},
totalSupplied: {
tokenAmount: '2.559M',
usdValue: '$2.559M',
tokenAmount: '962.8M',
usdValue: '$962.8M',
},
depositAPY: {
value: '5.90%',
// @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests
value: '8.52%',
},
totalBorrowed: {
tokenAmount: '2.077M',
usdValue: '$2.077M',
tokenAmount: '913.6M',
usdValue: '$913.6M',
},
borrowAPY: {
value: '7.72%',
value: '9.00%',
hasAirDrop: true,
},
status: {
// @note: This value is different in production since VITE_FEATURE_DISABLE_DAI_LEND is disabled in playwright tests
supply: 'Can be supplied',
collateral: 'Cannot be used as collateral',
borrow: 'Can be borrowed',
Expand Down Expand Up @@ -130,31 +110,6 @@ test.describe('Markets', () => {
borrow: 'Can be borrowed',
},
},
{
asset: {
name: 'Lido Staked ETH',
symbol: 'wstETH',
},
totalSupplied: {
tokenAmount: '519K',
usdValue: '$2.06B',
},
depositAPY: {
value: '<0.01%',
},
totalBorrowed: {
tokenAmount: '51.56',
usdValue: '$204.7K',
},
borrowAPY: {
value: '0.25%',
},
status: {
supply: 'Can be supplied',
collateral: 'Can be used as collateral',
borrow: 'Can be borrowed',
},
},
{
asset: {
name: 'Wrapped BTC',
Expand Down Expand Up @@ -207,22 +162,62 @@ test.describe('Markets', () => {
},
{
asset: {
name: 'Tether USD',
symbol: 'USDT',
name: 'Ether.fi Staked ETH',
symbol: 'weETH',
},
totalSupplied: {
tokenAmount: '316.6K',
usdValue: '$316.6K',
tokenAmount: '11.66K',
usdValue: '$41.17M',
},
depositAPY: {
value: '4.03%',
value: '0.00%',
},
totalBorrowed: undefined,
borrowAPY: undefined,
status: {
supply: 'Can be supplied',
collateral: 'Can be used as collateral only in isolation mode',
borrow: 'Cannot be borrowed',
},
},
{
asset: {
name: 'Savings Dai',
symbol: 'sDAI',
},
totalSupplied: {
tokenAmount: '13.49M',
usdValue: '$14.73M',
},
depositAPY: {
value: '0.00%',
},
totalBorrowed: undefined,
borrowAPY: undefined,
status: {
supply: 'Can be supplied',
collateral: 'Can be used as collateral',
borrow: 'Cannot be borrowed',
},
},
{
asset: {
name: 'Circle USD',
symbol: 'USDC',
},
totalSupplied: {
tokenAmount: '2.559M',
usdValue: '$2.559M',
},
depositAPY: {
value: '5.90%',
},
totalBorrowed: {
tokenAmount: '213.2K',
usdValue: '$213.2K',
tokenAmount: '2.077M',
usdValue: '$2.077M',
},
borrowAPY: {
value: '6.36%',
value: '7.72%',
},
status: {
supply: 'Can be supplied',
Expand All @@ -232,22 +227,27 @@ test.describe('Markets', () => {
},
{
asset: {
name: 'Ether.fi Staked ETH',
symbol: 'weETH',
name: 'Tether USD',
symbol: 'USDT',
},
totalSupplied: {
tokenAmount: '11.66K',
usdValue: '$41.17M',
tokenAmount: '316.6K',
usdValue: '$316.6K',
},
depositAPY: {
value: '0.00%',
value: '4.03%',
},
totalBorrowed: {
tokenAmount: '213.2K',
usdValue: '$213.2K',
},
borrowAPY: {
value: '6.36%',
},
totalBorrowed: undefined,
borrowAPY: undefined,
status: {
supply: 'Can be supplied',
collateral: 'Can be used as collateral only in isolation mode',
borrow: 'Cannot be borrowed',
collateral: 'Cannot be used as collateral',
borrow: 'Can be borrowed',
},
},
])
Expand Down
17 changes: 9 additions & 8 deletions packages/app/src/ui/molecules/data-table/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ export interface RowClickOptions {
destination: string
external?: boolean
}
interface RowType {
export interface DataTableRowType {
[k: string]: any
rowClickOptions?: RowClickOptions
}

export interface DataTableProps<T extends RowType> {
columnDef: {
[key: string]: ColumnDefinition<T>
}
export type DataTableColumnDefinitions<T extends DataTableRowType> = Record<string, ColumnDefinition<T>>
export interface DataTableProps<T extends DataTableRowType, C extends DataTableColumnDefinitions<T>> {
columnDef: C
scroll?: {
height: number
}
defaultSortingState?: { id: keyof C; desc: boolean }[]
hideTableHeader?: boolean
gridTemplateColumnsClassName?: string
data: T[]
Expand All @@ -43,16 +43,17 @@ export interface DataTableProps<T extends RowType> {
* If this is the problem, take care of memoizing columnDef outside of the component, so react knows that
* passed object is the same between renders, which will prevent unnecessary re-mount.
*/
export function DataTable<T extends RowType>({
export function DataTable<T extends DataTableRowType, C extends DataTableColumnDefinitions<T>>({
columnDef,
data,
scroll,
hideTableHeader = false,
defaultSortingState = [],
gridTemplateColumnsClassName,
footer,
'data-testid': dataTestId,
}: DataTableProps<T>) {
const [sorting, setSorting] = useState<SortingState>([])
}: DataTableProps<T, C>) {
const [sorting, setSorting] = useState<SortingState>(defaultSortingState as SortingState)

const columns: ColumnDef<T>[] = useMemo(() => {
return Object.keys(columnDef).map<ColumnDef<T>>((key) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import { Table, TableBody, TableHead, TableHeader, TableRow } from '@/ui/atoms/table/Table'
import { ColumnDefinition } from '@/ui/molecules/data-table/types'
import { testIds } from '@/ui/utils/testIds'
import { useBreakpoint } from '@/ui/utils/useBreakpoint'
import { Fragment } from 'react'
import { DataTable } from '../../molecules/data-table/DataTable'
import { DataTable, DataTableColumnDefinitions, DataTableRowType } from '../../molecules/data-table/DataTable'
import { CollapsibleCell } from './components/CollapsibleCell'

export interface ResponsiveDataTableProps<T> {
columnDefinition: { [key: string]: ColumnDefinition<T> }
export interface ResponsiveDataTableProps<T extends DataTableRowType, C extends DataTableColumnDefinitions<T>> {
columnDefinition: C
scroll?: {
height: number
}
defaultSortingState?: { id: keyof C; desc: boolean }[]
hideTableHeader?: boolean
gridTemplateColumnsClassName?: string
data: T[]
'data-testid'?: string
}

export function ResponsiveDataTable<T extends { [k: string]: any }>({
export function ResponsiveDataTable<T extends { [k: string]: any }, C extends DataTableColumnDefinitions<T>>({
columnDefinition,
data,
defaultSortingState,
scroll,
gridTemplateColumnsClassName,
hideTableHeader = false,
'data-testid': dataTestId,
}: ResponsiveDataTableProps<T>) {
}: ResponsiveDataTableProps<T, C>) {
const desktop = useBreakpoint('md')

if (desktop) {
return (
<DataTable
columnDef={columnDefinition}
data={data}
defaultSortingState={defaultSortingState}
scroll={scroll}
gridTemplateColumnsClassName={gridTemplateColumnsClassName}
hideTableHeader={hideTableHeader}
Expand Down

0 comments on commit eac3a74

Please sign in to comment.