diff --git a/__tests__/components/MarketAssetTable/MarketDetails.test.tsx b/__tests__/components/MarketAssetTable/MarketDetails.test.tsx deleted file mode 100644 index 75b193c4..00000000 --- a/__tests__/components/MarketAssetTable/MarketDetails.test.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { render } from '@testing-library/react' - -import MarketDetails from 'components/MarketAssetTable/MarketDetails' -import { ASSETS } from 'constants/assets' -import { BN } from 'utils/helpers' - -const data: LendingMarketTableData = { - asset: ASSETS[0], - marketDepositAmount: BN('890546916'), - accountLentValue: BN('0.5498406009348686811'), - marketLiquidityAmount: BN('629396551'), - marketDepositCap: BN('2500000000000'), - marketLiquidityRate: 0.017, - marketLiquidationThreshold: 0.61, - marketMaxLtv: 0.59, - borrowEnabled: true, -} - -jest.mock('hooks/useDisplayCurrencyPrice', () => () => { - const { BN } = require('utils/helpers') - - return { - getConversionRate: () => BN(1), - convertAmount: () => BN(1), - symbol: 'MARS', - } -}) - -describe('', () => { - afterAll(() => { - jest.unmock('hooks/usePrices') - }) - - it('should render', () => { - const { container } = render() - expect(container).toBeInTheDocument() - }) -}) diff --git a/__tests__/components/Modals/Unlock/UnlockModal.test.tsx b/__tests__/components/Modals/Unlock/UnlockModal.test.tsx index 2297fa19..c19fbdf3 100644 --- a/__tests__/components/Modals/Unlock/UnlockModal.test.tsx +++ b/__tests__/components/Modals/Unlock/UnlockModal.test.tsx @@ -14,6 +14,7 @@ const mockedDepositedVault: DepositedVault = { ...TESTNET_VAULTS_META_DATA[0], status: 'active', apy: 1, + apr: null, ltv: { max: 0.65, liq: 0.7, diff --git a/__tests__/components/Modals/vault/VaultBorrowings.test.tsx b/__tests__/components/Modals/vault/VaultBorrowings.test.tsx deleted file mode 100644 index a1b7be74..00000000 --- a/__tests__/components/Modals/vault/VaultBorrowings.test.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { render } from '@testing-library/react' - -import DisplayCurrency from 'components/DisplayCurrency' -import VaultBorrowings, { VaultBorrowingsProps } from 'components/Modals/Vault/VaultBorrowings' -import { ASSETS } from 'constants/assets' -import { TESTNET_VAULTS_META_DATA } from 'constants/vaults' -import useStore from 'store' -import { BNCoin } from 'types/classes/BNCoin' -import { BN } from 'utils/helpers' - -jest.mock('hooks/usePrices', () => - jest.fn(() => ({ - data: [], - })), -) - -jest.mock('hooks/usePrice', () => jest.fn(() => '1')) - -jest.mock('hooks/useMarketAssets', () => - jest.fn(() => ({ - data: [], - })), -) - -jest.mock('hooks/broadcast/useDepositVault', () => jest.fn(() => ({ actions: [] }))) - -jest.mock('components/DisplayCurrency') - -jest.mock('hooks/useHealthComputer', () => - jest.fn(() => ({ - computeMaxBorrowAmount: () => {}, - })), -) - -const mockedDisplayCurrency = jest - .mocked(DisplayCurrency) - .mockImplementation(() =>
Display currency
) - -const mockedVault: Vault = { - ...TESTNET_VAULTS_META_DATA[0], - apy: 0, - ltv: { - liq: 0.2, - max: 0.1, - }, - cap: { - denom: 'test', - max: BN(10), - used: BN(2), - }, -} -describe('', () => { - const defaultProps: VaultBorrowingsProps = { - primaryAsset: ASSETS[0], - secondaryAsset: ASSETS[1], - vault: mockedVault, - borrowings: [], - deposits: [], - onChangeBorrowings: jest.fn(), - depositActions: [], - depositCapReachedCoins: [], - displayCurrency: 'uosmo', - } - - beforeAll(() => { - useStore.setState({ - baseCurrency: ASSETS[0], - }) - }) - - afterAll(() => { - useStore.clearState() - mockedDisplayCurrency.mockClear() - }) - - it('should render', () => { - const { container } = render() - expect(container).toBeInTheDocument() - }) - - it('should render DisplayCurrency correctly', () => { - expect(mockedDisplayCurrency).toHaveBeenCalledTimes(1) - expect(mockedDisplayCurrency).toHaveBeenCalledWith( - { coin: new BNCoin({ denom: 'usd', amount: '0' }) }, - expect.anything(), - ) - }) -}) diff --git a/__tests__/components/Tooltip/TooltipContent.test.tsx b/__tests__/components/Tooltip/TooltipContent.test.tsx index 0f84091d..a7e114c1 100644 --- a/__tests__/components/Tooltip/TooltipContent.test.tsx +++ b/__tests__/components/Tooltip/TooltipContent.test.tsx @@ -1,6 +1,5 @@ import { render } from '@testing-library/react' -import { TooltipType } from 'components/Tooltip' import TooltipContent from 'components/Tooltip/TooltipContent' describe('', () => { diff --git a/src/components/Account/AccountComposition.tsx b/src/components/Account/AccountComposition.tsx index e24b6522..f6c0a3c5 100644 --- a/src/components/Account/AccountComposition.tsx +++ b/src/components/Account/AccountComposition.tsx @@ -37,14 +37,10 @@ export default function AccountComposition(props: Props) { const { account } = props const hasChanged = !!updatedAccount const { data: prices } = usePrices() - const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } = - useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssetsData = useMemo(() => data?.allAssets || [], [data]) const { availableAssets: lendingAvailableAssets, accountLentAssets } = useLendingMarketAssetsTableData() - const borrowAssetsData = useMemo( - () => [...borrowAvailableAssets, ...accountBorrowedAssets], - [borrowAvailableAssets, accountBorrowedAssets], - ) const lendingAssetsData = useMemo( () => [...lendingAvailableAssets, ...accountLentAssets], [lendingAvailableAssets, accountLentAssets], diff --git a/src/components/Account/AccountDetails/index.tsx b/src/components/Account/AccountDetails/index.tsx index 9d6ffe57..18e999cc 100644 --- a/src/components/Account/AccountDetails/index.tsx +++ b/src/components/Account/AccountDetails/index.tsx @@ -76,14 +76,12 @@ function AccountDetails(props: Props) { return updatedLeverage }, [updatedAccount, prices, leverage]) - const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } = - useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssetsData = useMemo(() => data?.allAssets || [], [data]) + const { availableAssets: lendingAvailableAssets, accountLentAssets } = useLendingMarketAssetsTableData() - const borrowAssetsData = useMemo( - () => [...borrowAvailableAssets, ...accountBorrowedAssets], - [borrowAvailableAssets, accountBorrowedAssets], - ) + const lendingAssetsData = useMemo( () => [...lendingAvailableAssets, ...accountLentAssets], [lendingAvailableAssets, accountLentAssets], diff --git a/src/components/Account/AccountList/AccountStats.tsx b/src/components/Account/AccountList/AccountStats.tsx index 92a656e2..2ff13667 100644 --- a/src/components/Account/AccountList/AccountStats.tsx +++ b/src/components/Account/AccountList/AccountStats.tsx @@ -28,14 +28,10 @@ export default function AccountStats(props: Props) { [account, prices], ) const { health } = useHealthComputer(account) - const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } = - useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssetsData = useMemo(() => data?.allAssets || [], [data]) const { availableAssets: lendingAvailableAssets, accountLentAssets } = useLendingMarketAssetsTableData() - const borrowAssetsData = useMemo( - () => [...borrowAvailableAssets, ...accountBorrowedAssets], - [borrowAvailableAssets, accountBorrowedAssets], - ) const lendingAssetsData = useMemo( () => [...lendingAvailableAssets, ...accountLentAssets], [lendingAvailableAssets, accountLentAssets], diff --git a/src/components/Account/AccountSummary.tsx b/src/components/Account/AccountSummary.tsx index de914b20..25ab386a 100644 --- a/src/components/Account/AccountSummary.tsx +++ b/src/components/Account/AccountSummary.tsx @@ -36,15 +36,11 @@ export default function AccountSummary(props: Props) { : BN_ZERO, [props.account, updatedAccount, prices], ) - const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } = - useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssetsData = useMemo(() => data?.allAssets || [], [data]) const { availableAssets: lendingAvailableAssets, accountLentAssets } = useLendingMarketAssetsTableData() - const borrowAssetsData = useMemo( - () => [...borrowAvailableAssets, ...accountBorrowedAssets], - [borrowAvailableAssets, accountBorrowedAssets], - ) const lendingAssetsData = useMemo( () => [...lendingAvailableAssets, ...accountLentAssets], [lendingAvailableAssets, accountLentAssets], diff --git a/src/components/Borrow/BorrowTable.tsx b/src/components/Borrow/BorrowTable.tsx deleted file mode 100644 index 440693e3..00000000 --- a/src/components/Borrow/BorrowTable.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { ColumnDef, Row, Table } from '@tanstack/react-table' -import { useCallback, useMemo } from 'react' - -import AmountAndValue from 'components/AmountAndValue' -import AssetImage from 'components/Asset/AssetImage' -import BorrowActionButtons from 'components/Borrow/BorrowActionButtons' -import { FormattedNumber } from 'components/FormattedNumber' -import { ChevronDown, ChevronUp } from 'components/Icons' -import Loading from 'components/Loading' -import AssetListTable from 'components/MarketAssetTable' -import MarketAssetTableRow from 'components/MarketAssetTable/MarketAssetTableRow' -import MarketDetails from 'components/MarketAssetTable/MarketDetails' -import TitleAndSubCell from 'components/TitleAndSubCell' -import { BN_ZERO } from 'constants/math' -import { getEnabledMarketAssets } from 'utils/assets' - -interface Props { - title: string - data: BorrowMarketTableData[] -} - -export default function BorrowTable(props: Props) { - const { title, data } = props - const shouldShowAccountBorrowed = !!data[0]?.debt - const marketAssets = getEnabledMarketAssets() - - const rowRenderer = useCallback( - (row: Row, table: Table) => { - return ( - } - expandedDetails={} - /> - ) - }, - [], - ) - - const columns = useMemo[]>( - () => [ - { - accessorKey: 'asset.name', - header: 'Asset', - id: 'symbol', - cell: ({ row }) => { - const asset = row.original.asset - - return ( -
- - -
- ) - }, - }, - ...(shouldShowAccountBorrowed - ? [ - { - accessorKey: 'debt', - header: 'Borrowed', - cell: (info: any) => { - const borrowAsset = info.row.original as BorrowMarketTableData - const asset = marketAssets.find((asset) => asset.denom === borrowAsset.asset.denom) - - if (!asset) return null - - return - }, - }, - ] - : []), - { - accessorKey: 'borrowRate', - header: 'Borrow Rate', - cell: ({ row }) => { - if (row.original.borrowRate === null) { - return - } - - return ( - - ) - }, - }, - { - accessorKey: 'liquidity', - header: 'Liquidity Available', - cell: ({ row }) => { - const { liquidity, asset: borrowAsset } = row.original - const asset = marketAssets.find((asset) => asset.denom === borrowAsset.denom) - - if (!asset) return null - - if (liquidity === null) { - return - } - - return - }, - }, - { - accessorKey: 'manage', - enableSorting: false, - header: 'Manage', - cell: ({ row }) => ( -
-
{row.getIsExpanded() ? : }
-
- ), - }, - ], - [shouldShowAccountBorrowed, marketAssets], - ) - - return -} diff --git a/src/components/Borrow/Borrowings.tsx b/src/components/Borrow/Borrowings.tsx new file mode 100644 index 00000000..ca72ff0d --- /dev/null +++ b/src/components/Borrow/Borrowings.tsx @@ -0,0 +1,37 @@ +import React from 'react' + +import AvailableBorrowingsTable from 'components/Borrow/Table/AvailableBorrowingsTable' +import DepositedBorrowingsTable from 'components/Borrow/Table/DepositedBorrowingsTable' +import { BN_ZERO } from 'constants/math' +import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' +import { getBorrowEnabledAssets } from 'utils/assets' + +export default function Borrowings() { + const { data } = useBorrowMarketAssetsTableData() + + if (!data?.allAssets?.length) { + return + } + return ( + <> + + + + ) +} + +function Fallback() { + const assets = getBorrowEnabledAssets() + const data: BorrowMarketTableData[] = assets.map((asset) => ({ + asset, + borrowRate: null, + liquidity: null, + marketMaxLtv: 0, + marketDepositAmount: BN_ZERO, + marketLiquidityRate: 0, + marketLiquidityAmount: BN_ZERO, + marketLiquidationThreshold: 0, + })) + + return +} diff --git a/src/components/Borrow/Table/AvailableBorrowingsTable.tsx b/src/components/Borrow/Table/AvailableBorrowingsTable.tsx new file mode 100644 index 00000000..147d5b24 --- /dev/null +++ b/src/components/Borrow/Table/AvailableBorrowingsTable.tsx @@ -0,0 +1,40 @@ +import { Row } from '@tanstack/react-table' +import { Table as TanstackTable } from '@tanstack/table-core/build/lib/types' +import React, { useCallback } from 'react' + +import useAvailableColumns from 'components/Borrow/Table/Columns/useAvailableColumns' +import Card from 'components/Card' +import MarketDetails from 'components/MarketDetails' +import Table from 'components/Table' + +type Props = { + data: BorrowMarketTableData[] + isLoading: boolean +} + +export default function AvailableBorrowingsTable(props: Props) { + const columns = useAvailableColumns({ isLoading: props.isLoading }) + + const renderExpanded = useCallback( + (row: Row, _: TanstackTable) => ( + } + type='borrow' + /> + ), + [], + ) + + if (!props.data.length) return null + + return ( + + + + ) +} diff --git a/src/components/Borrow/Table/Columns/BorrowRate.tsx b/src/components/Borrow/Table/Columns/BorrowRate.tsx new file mode 100644 index 00000000..d221d65d --- /dev/null +++ b/src/components/Borrow/Table/Columns/BorrowRate.tsx @@ -0,0 +1,25 @@ +import React from 'react' + +import { FormattedNumber } from 'components/FormattedNumber' +import Loading from 'components/Loading' + +export const BORROW_RATE_META = { accessorKey: 'borrowRate', header: 'Borrow Rate' } + +interface Props { + borrowRate: number | null +} + +export default function BorrowRate(props: Props) { + if (props.borrowRate === null) { + return + } + + return ( + + ) +} diff --git a/src/components/Borrow/Table/Columns/Debt.tsx b/src/components/Borrow/Table/Columns/Debt.tsx new file mode 100644 index 00000000..8aaad2bf --- /dev/null +++ b/src/components/Borrow/Table/Columns/Debt.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +import AmountAndValue from 'components/AmountAndValue' +import { BN_ZERO } from 'constants/math' +import { getEnabledMarketAssets } from 'utils/assets' + +export const DEBT_META = { + accessorKey: 'debt', + header: 'Debt', +} +interface Props { + data: BorrowMarketTableData +} + +export default function Debt(props: Props) { + const marketAssets = getEnabledMarketAssets() + const asset = marketAssets.find((asset) => asset.denom === props.data.asset.denom) + + if (!asset) return null + + return +} diff --git a/src/components/Borrow/Table/Columns/Liquidity.tsx b/src/components/Borrow/Table/Columns/Liquidity.tsx new file mode 100644 index 00000000..3a955275 --- /dev/null +++ b/src/components/Borrow/Table/Columns/Liquidity.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +import AmountAndValue from 'components/AmountAndValue' +import Loading from 'components/Loading' +import { BN_ZERO } from 'constants/math' +import { getEnabledMarketAssets } from 'utils/assets' + +export const LIQUIDITY_META = { accessorKey: 'asset.name', header: 'Asset', id: 'symbol' } +interface Props { + data: BorrowMarketTableData +} +export default function Liquidity(props: Props) { + const { liquidity, asset: borrowAsset } = props.data + const marketAssets = getEnabledMarketAssets() + const asset = marketAssets.find((asset) => asset.denom === borrowAsset.denom) + + if (!asset) return null + + if (liquidity === null) { + return + } + + return +} diff --git a/src/components/Borrow/Table/Columns/Manage.tsx b/src/components/Borrow/Table/Columns/Manage.tsx new file mode 100644 index 00000000..58c95820 --- /dev/null +++ b/src/components/Borrow/Table/Columns/Manage.tsx @@ -0,0 +1,17 @@ +import React from 'react' + +import { ChevronDown, ChevronUp } from 'components/Icons' + +export const MANAGE_META = { accessorKey: 'manage', enableSorting: false, header: 'Manage' } + +interface Props { + isExpanded: boolean +} + +export default function Manage(props: Props) { + return ( +
+
{props.isExpanded ? : }
+
+ ) +} diff --git a/src/components/Borrow/Table/Columns/Name.tsx b/src/components/Borrow/Table/Columns/Name.tsx new file mode 100644 index 00000000..331ef0b4 --- /dev/null +++ b/src/components/Borrow/Table/Columns/Name.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +import AssetImage from 'components/Asset/AssetImage' +import TitleAndSubCell from 'components/TitleAndSubCell' + +export const NAME_META = { accessorKey: 'asset.name', header: 'Asset', id: 'symbol' } + +interface Props { + data: BorrowMarketTableData +} + +export default function Name(props: Props) { + const { asset } = props.data + return ( +
+ + +
+ ) +} diff --git a/src/components/Borrow/Table/Columns/useAvailableColumns.tsx b/src/components/Borrow/Table/Columns/useAvailableColumns.tsx new file mode 100644 index 00000000..289fb661 --- /dev/null +++ b/src/components/Borrow/Table/Columns/useAvailableColumns.tsx @@ -0,0 +1,34 @@ +import { ColumnDef } from '@tanstack/react-table' +import React, { useMemo } from 'react' + +import BorrowRate, { BORROW_RATE_META } from 'components/Borrow/Table/Columns/BorrowRate' +import Liquidity, { LIQUIDITY_META } from 'components/Borrow/Table/Columns/Liquidity' +import Manage, { MANAGE_META } from 'components/Borrow/Table/Columns/Manage' +import Name, { NAME_META } from 'components/Borrow/Table/Columns/Name' + +interface Props { + isLoading: boolean +} + +export default function useAvailableColumns(props: Props) { + return useMemo[]>(() => { + return [ + { + ...NAME_META, + cell: ({ row }) => , + }, + { + ...BORROW_RATE_META, + cell: ({ row }) => , + }, + { + ...LIQUIDITY_META, + cell: ({ row }) => , + }, + { + ...MANAGE_META, + cell: ({ row }) => , + }, + ] + }, []) +} diff --git a/src/components/Borrow/Table/Columns/useDepositedColumns.tsx b/src/components/Borrow/Table/Columns/useDepositedColumns.tsx new file mode 100644 index 00000000..ab95f5a5 --- /dev/null +++ b/src/components/Borrow/Table/Columns/useDepositedColumns.tsx @@ -0,0 +1,39 @@ +import { ColumnDef } from '@tanstack/react-table' +import React, { useMemo } from 'react' + +import BorrowRate, { BORROW_RATE_META } from 'components/Borrow/Table/Columns/BorrowRate' +import Debt, { DEBT_META } from 'components/Borrow/Table/Columns/Debt' +import Liquidity, { LIQUIDITY_META } from 'components/Borrow/Table/Columns/Liquidity' +import Manage, { MANAGE_META } from 'components/Borrow/Table/Columns/Manage' +import Name, { NAME_META } from 'components/Borrow/Table/Columns/Name' + +interface Props { + isLoading: boolean +} + +export default function useDepositedColumns(props: Props) { + return useMemo[]>(() => { + return [ + { + ...NAME_META, + cell: ({ row }) => , + }, + { + ...DEBT_META, + cell: ({ row }) => , + }, + { + ...BORROW_RATE_META, + cell: ({ row }) => , + }, + { + ...LIQUIDITY_META, + cell: ({ row }) => , + }, + { + ...MANAGE_META, + cell: ({ row }) => , + }, + ] + }, []) +} diff --git a/src/components/Borrow/Table/DepositedBorrowingsTable.tsx b/src/components/Borrow/Table/DepositedBorrowingsTable.tsx new file mode 100644 index 00000000..179704f2 --- /dev/null +++ b/src/components/Borrow/Table/DepositedBorrowingsTable.tsx @@ -0,0 +1,38 @@ +import { Row } from '@tanstack/react-table' +import { Table as TanStackTable } from '@tanstack/table-core/build/lib/types' +import React, { useCallback } from 'react' + +import useDepositedColumns from 'components/Borrow/Table/Columns/useDepositedColumns' +import Card from 'components/Card' +import MarketDetails from 'components/MarketDetails' +import Table from 'components/Table' + +type Props = { + data: BorrowMarketTableData[] + isLoading: boolean +} + +export default function DepositedBorrowingsTable(props: Props) { + const columns = useDepositedColumns({ isLoading: props.isLoading }) + + const renderExpanded = useCallback( + ( + row: Row, + table: TanStackTable, + ) => , + [], + ) + + if (!props.data.length) return null + + return ( + +
+ + ) +} diff --git a/src/components/Earn/Farm/Table/AvailableVaultsTable.tsx b/src/components/Earn/Farm/Table/AvailableVaultsTable.tsx index b55aca41..aeb36739 100644 --- a/src/components/Earn/Farm/Table/AvailableVaultsTable.tsx +++ b/src/components/Earn/Farm/Table/AvailableVaultsTable.tsx @@ -11,6 +11,7 @@ type Props = { export default function AvailableVaultsTable(props: Props) { const columns = useAvailableColumns({ isLoading: props.isLoading }) + return (
diff --git a/src/components/Earn/Farm/Table/Columns/Apy.tsx b/src/components/Earn/Farm/Table/Columns/Apy.tsx index 947b5e69..e1000ed6 100644 --- a/src/components/Earn/Farm/Table/Columns/Apy.tsx +++ b/src/components/Earn/Farm/Table/Columns/Apy.tsx @@ -3,6 +3,8 @@ import React from 'react' import { FormattedNumber } from 'components/FormattedNumber' import Loading from 'components/Loading' +export const APY_META = { accessorKey: 'apy', header: 'APY' } + interface Props { vault: Vault | DepositedVault } diff --git a/src/components/Earn/Farm/Table/Columns/DepositCap.tsx b/src/components/Earn/Farm/Table/Columns/DepositCap.tsx index c661e020..f68c02bc 100644 --- a/src/components/Earn/Farm/Table/Columns/DepositCap.tsx +++ b/src/components/Earn/Farm/Table/Columns/DepositCap.tsx @@ -6,6 +6,8 @@ import TitleAndSubCell from 'components/TitleAndSubCell' import { VAULT_DEPOSIT_BUFFER } from 'constants/vaults' import { getAssetByDenom } from 'utils/assets' +export const DEPOSIT_CAP_META = { accessorKey: 'cap', header: 'Deposit Cap' } + interface Props { vault: Vault | DepositedVault isLoading: boolean diff --git a/src/components/Earn/Farm/Table/Columns/Details.tsx b/src/components/Earn/Farm/Table/Columns/Details.tsx index e642c83f..65e920c5 100644 --- a/src/components/Earn/Farm/Table/Columns/Details.tsx +++ b/src/components/Earn/Farm/Table/Columns/Details.tsx @@ -4,6 +4,8 @@ import React from 'react' import { ChevronDown } from 'components/Icons' import Loading from 'components/Loading' +export const DETAILS_META = { accessorKey: 'details', enableSorting: false, header: 'Deposit' } + interface Props { isLoading: boolean isExpanded: boolean diff --git a/src/components/Earn/Farm/Table/Columns/MaxLTV.tsx b/src/components/Earn/Farm/Table/Columns/MaxLTV.tsx index bf322aeb..7d90c756 100644 --- a/src/components/Earn/Farm/Table/Columns/MaxLTV.tsx +++ b/src/components/Earn/Farm/Table/Columns/MaxLTV.tsx @@ -3,6 +3,8 @@ import React from 'react' import { FormattedNumber } from 'components/FormattedNumber' import Loading from 'components/Loading' +export const LTV_MAX_META = { accessorKey: 'ltv.max', header: 'Max LTV' } + interface Props { vault: Vault | DepositedVault isLoading: boolean diff --git a/src/components/Earn/Farm/Table/Columns/Name.tsx b/src/components/Earn/Farm/Table/Columns/Name.tsx index 6e6fab92..30b9992f 100644 --- a/src/components/Earn/Farm/Table/Columns/Name.tsx +++ b/src/components/Earn/Farm/Table/Columns/Name.tsx @@ -7,6 +7,7 @@ import TitleAndSubCell from 'components/TitleAndSubCell' import { VaultStatus } from 'types/enums/vault' import { produceCountdown } from 'utils/formatters' +export const NAME_META = { header: 'Vault', accessorKey: 'name' } interface Props { vault: Vault | DepositedVault } diff --git a/src/components/Earn/Farm/Table/Columns/PositionValue.tsx b/src/components/Earn/Farm/Table/Columns/PositionValue.tsx index 916c26b9..b3e4590d 100644 --- a/src/components/Earn/Farm/Table/Columns/PositionValue.tsx +++ b/src/components/Earn/Farm/Table/Columns/PositionValue.tsx @@ -4,6 +4,10 @@ import DisplayCurrency from 'components/DisplayCurrency' import { ORACLE_DENOM } from 'constants/oracle' import { BNCoin } from 'types/classes/BNCoin' +export const POSITION_VALUE_META = { + header: 'Pos. Value', +} + interface Props { vault: DepositedVault isLoading: boolean diff --git a/src/components/Earn/Farm/Table/Columns/TVL.tsx b/src/components/Earn/Farm/Table/Columns/TVL.tsx index 122725e0..8b9e1b9b 100644 --- a/src/components/Earn/Farm/Table/Columns/TVL.tsx +++ b/src/components/Earn/Farm/Table/Columns/TVL.tsx @@ -4,6 +4,8 @@ import DisplayCurrency from 'components/DisplayCurrency' import Loading from 'components/Loading' import { BNCoin } from 'types/classes/BNCoin' +export const TVL_META = { accessorKey: 'tvl', header: 'TVL' } + interface Props { vault: Vault | DepositedVault isLoading: boolean diff --git a/src/components/Earn/Farm/Table/Columns/useAvailableColumns.tsx b/src/components/Earn/Farm/Table/Columns/useAvailableColumns.tsx index f3d0d53a..f9f0e0f4 100644 --- a/src/components/Earn/Farm/Table/Columns/useAvailableColumns.tsx +++ b/src/components/Earn/Farm/Table/Columns/useAvailableColumns.tsx @@ -1,12 +1,14 @@ import { ColumnDef } from '@tanstack/react-table' import React, { useMemo } from 'react' -import Apy from 'components/Earn/Farm/Table/Columns/Apy' +import Apy, { APY_META } from 'components/Earn/Farm/Table/Columns/Apy' import { Deposit } from 'components/Earn/Farm/Table/Columns/Deposit' -import DepositCap from 'components/Earn/Farm/Table/Columns/DepositCap' -import MaxLTV from 'components/Earn/Farm/Table/Columns/MaxLTV' -import Name from 'components/Earn/Farm/Table/Columns/Name' -import TVL from 'components/Earn/Farm/Table/Columns/TVL' +import DepositCap, { DEPOSIT_CAP_META } from 'components/Earn/Farm/Table/Columns/DepositCap' +import MaxLTV, { LTV_MAX_META } from 'components/Earn/Farm/Table/Columns/MaxLTV' +import Name, { NAME_META } from 'components/Earn/Farm/Table/Columns/Name' +import TVL, { TVL_META } from 'components/Earn/Farm/Table/Columns/TVL' + +import { DETAILS_META } from './Details' interface Props { isLoading: boolean @@ -16,34 +18,27 @@ export default function useAvailableColumns(props: Props) { return useMemo[]>(() => { return [ { - header: 'Vault', - accessorKey: 'name', + ...NAME_META, cell: ({ row }) => , }, { - accessorKey: 'apy', - header: 'APY', + ...APY_META, cell: ({ row }) => , }, { - accessorKey: 'tvl', - header: 'TVL', + ...TVL_META, cell: ({ row }) => , }, { - accessorKey: 'cap', - header: 'Deposit Cap', + ...DEPOSIT_CAP_META, cell: ({ row }) => , }, { - accessorKey: 'ltv.max', - header: 'Max LTV', + ...LTV_MAX_META, cell: ({ row }) => , }, { - accessorKey: 'details', - enableSorting: false, - header: 'Deposit', + ...DETAILS_META, cell: ({ row }) => , }, ] diff --git a/src/components/Earn/Farm/Table/Columns/useDepositedColumns.tsx b/src/components/Earn/Farm/Table/Columns/useDepositedColumns.tsx index d44c9c94..35fb20be 100644 --- a/src/components/Earn/Farm/Table/Columns/useDepositedColumns.tsx +++ b/src/components/Earn/Farm/Table/Columns/useDepositedColumns.tsx @@ -1,13 +1,15 @@ import { ColumnDef, Row } from '@tanstack/react-table' import React, { useMemo } from 'react' -import Apy from 'components/Earn/Farm/Table/Columns/Apy' -import DepositCap from 'components/Earn/Farm/Table/Columns/DepositCap' -import Details from 'components/Earn/Farm/Table/Columns/Details' -import MaxLTV from 'components/Earn/Farm/Table/Columns/MaxLTV' -import Name from 'components/Earn/Farm/Table/Columns/Name' -import PositionValue from 'components/Earn/Farm/Table/Columns/PositionValue' -import TVL from 'components/Earn/Farm/Table/Columns/TVL' +import Apy, { APY_META } from 'components/Earn/Farm/Table/Columns/Apy' +import DepositCap, { DEPOSIT_CAP_META } from 'components/Earn/Farm/Table/Columns/DepositCap' +import Details, { DETAILS_META } from 'components/Earn/Farm/Table/Columns/Details' +import MaxLTV, { LTV_MAX_META } from 'components/Earn/Farm/Table/Columns/MaxLTV' +import Name, { NAME_META } from 'components/Earn/Farm/Table/Columns/Name' +import PositionValue, { + POSITION_VALUE_META, +} from 'components/Earn/Farm/Table/Columns/PositionValue' +import TVL, { TVL_META } from 'components/Earn/Farm/Table/Columns/TVL' interface Props { isLoading: boolean @@ -17,46 +19,39 @@ export default function useDepositedColumns(props: Props) { return useMemo[]>(() => { return [ { - header: 'Vault', - accessorKey: 'name', + ...NAME_META, cell: ({ row }) => , }, { - header: 'Pos. Value', + ...POSITION_VALUE_META, cell: ({ row }: { row: Row }) => ( ), }, { - accessorKey: 'apy', - header: 'APY', + ...APY_META, cell: ({ row }) => , }, { - accessorKey: 'tvl', - header: 'TVL', + ...TVL_META, cell: ({ row }) => ( ), }, { - accessorKey: 'cap', - header: 'Deposit Cap', + ...DEPOSIT_CAP_META, cell: ({ row }) => ( ), }, { - accessorKey: 'ltv.max', - header: 'Max LTV', + ...LTV_MAX_META, cell: ({ row }) => ( ), }, { - accessorKey: 'details', - enableSorting: false, - header: 'Details', + ...DETAILS_META, cell: ({ row }) =>
, }, ] diff --git a/src/components/Earn/Farm/Table/DepositedVaultsTable.tsx b/src/components/Earn/Farm/Table/DepositedVaultsTable.tsx index 13486f3f..1d18f25f 100644 --- a/src/components/Earn/Farm/Table/DepositedVaultsTable.tsx +++ b/src/components/Earn/Farm/Table/DepositedVaultsTable.tsx @@ -1,7 +1,10 @@ -import React from 'react' +import { Row } from '@tanstack/react-table' +import { Table as TanStackTable } from '@tanstack/table-core/build/lib/types' +import React, { useCallback } from 'react' import Card from 'components/Card' import useDepositedColumns from 'components/Earn/Farm/Table/Columns/useDepositedColumns' +import VaultExpanded from 'components/Earn/Farm/VaultExpanded' import Table from 'components/Table' type Props = { @@ -11,9 +14,22 @@ type Props = { export default function DepositedVaultsTable(props: Props) { const columns = useDepositedColumns({ isLoading: props.isLoading }) + + const renderExpanded = useCallback( + (row: Row, table: TanStackTable) => ( + + ), + [], + ) + return ( -
+
) } diff --git a/src/components/Earn/Farm/VaultExpanded.tsx b/src/components/Earn/Farm/VaultExpanded.tsx index 5c4d7532..d58d3b1a 100644 --- a/src/components/Earn/Farm/VaultExpanded.tsx +++ b/src/components/Earn/Farm/VaultExpanded.tsx @@ -13,12 +13,12 @@ import useStore from 'store' import { VaultStatus } from 'types/enums/vault' interface Props { - row: Row + row: Row resetExpanded: (defaultState?: boolean | undefined) => void } export default function VaultExpanded(props: Props) { - const vault = props.row.original as DepositedVault + const vault = props.row.original const accountId = useAccountId() const [isConfirming, setIsConfirming] = useState(false) const withdrawFromVaults = useStore((s) => s.withdrawFromVaults) @@ -113,7 +113,7 @@ export default function VaultExpanded(props: Props) { !isExpanded && props.row.toggleExpanded() }} > - + ) } diff --git a/src/components/Portfolio/Account/Balances.tsx b/src/components/Portfolio/Account/Balances.tsx index d1736e94..e02be24a 100644 --- a/src/components/Portfolio/Account/Balances.tsx +++ b/src/components/Portfolio/Account/Balances.tsx @@ -1,4 +1,4 @@ -import React, { Suspense } from 'react' +import React, { Suspense, useMemo } from 'react' import AccountBalancesTable from 'components/Account/AccountBalancesTable' import Card from 'components/Card' @@ -15,7 +15,8 @@ interface Props { function Content(props: Props) { const { data: account } = useAccount(props.accountId, true) - const { allAssets: borrowAssets } = useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssets = useMemo(() => data?.allAssets || [], [data]) const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() if (!account || !borrowAssets.length || !lendingAssets.length) { diff --git a/src/components/Portfolio/Account/Summary.tsx b/src/components/Portfolio/Account/Summary.tsx index a5b8f4b0..39b18c1b 100644 --- a/src/components/Portfolio/Account/Summary.tsx +++ b/src/components/Portfolio/Account/Summary.tsx @@ -20,7 +20,8 @@ function Content(props: Props) { const { data: account } = useAccount(props.accountId, true) const { data: prices } = usePrices() const { health } = useHealthComputer(account) - const { allAssets: borrowAssets } = useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssets = useMemo(() => data?.allAssets || [], [data]) const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() const stats = useMemo(() => { diff --git a/src/components/Portfolio/Card/index.tsx b/src/components/Portfolio/Card/index.tsx index 1b9d009b..824aaf91 100644 --- a/src/components/Portfolio/Card/index.tsx +++ b/src/components/Portfolio/Card/index.tsx @@ -34,7 +34,8 @@ export default function PortfolioCard(props: Props) { const { data: prices } = usePrices() const currentAccountId = useAccountId() const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() - const { allAssets: borrowAssets } = useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssets = useMemo(() => data?.allAssets || [], [data]) const [reduceMotion] = useLocalStorage(REDUCE_MOTION_KEY, DEFAULT_SETTINGS.reduceMotion) const address = useStore((s) => s.address) diff --git a/src/components/Portfolio/Overview/Summary.tsx b/src/components/Portfolio/Overview/Summary.tsx index 3f45b79f..c0404f7a 100644 --- a/src/components/Portfolio/Overview/Summary.tsx +++ b/src/components/Portfolio/Overview/Summary.tsx @@ -17,7 +17,8 @@ export default function PortfolioSummary() { const { address: urlAddress } = useParams() const walletAddress = useStore((s) => s.address) const { data: prices } = usePrices() - const { allAssets: borrowAssets } = useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssets = useMemo(() => data?.allAssets || [], [data]) const { allAssets: lendingAssets } = useLendingMarketAssetsTableData() const { data: accounts } = useAccounts(urlAddress || walletAddress) diff --git a/src/components/Table/Row.tsx b/src/components/Table/Row.tsx new file mode 100644 index 00000000..63999a32 --- /dev/null +++ b/src/components/Table/Row.tsx @@ -0,0 +1,42 @@ +import { flexRender, Row as TanstackRow, Table as TanstackTable } from '@tanstack/react-table' +import classNames from 'classnames' + +interface Props { + row: TanstackRow + table: TanstackTable + renderExpanded?: (row: TanstackRow, table: TanstackTable) => JSX.Element + rowClassName?: string + rowClickHandler?: () => void +} + +export default function Row(props: Props) { + return ( + <> + { + e.preventDefault() + const isExpanded = props.row.getIsExpanded() + props.table.resetExpanded() + !isExpanded && props.row.toggleExpanded() + }} + > + {props.row.getVisibleCells().map((cell) => { + return ( + + ) + })} + + {props.row.getIsExpanded() && + props.renderExpanded && + props.renderExpanded(props.row, props.table)} + + ) +} diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index cf04a4a2..ae9d3be5 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -3,26 +3,26 @@ import { flexRender, getCoreRowModel, getSortedRowModel, - Row, SortingState, + Row as TanstackRow, + Table as TanstackTable, useReactTable, } from '@tanstack/react-table' import classNames from 'classnames' import React from 'react' -import VaultExpanded from 'components/Earn/Farm/VaultExpanded' -import { VaultRow } from 'components/Earn/Farm/VaultRow' import { SortAsc, SortDesc, SortNone } from 'components/Icons' +import Row from 'components/Table/Row' +import Text from 'components/Text' -import Text from '../Text' - -interface Props { - columns: ColumnDef[] - data: unknown[] +interface Props { + columns: ColumnDef[] + data: T[] initialSorting: SortingState + renderExpanded?: (row: TanstackRow, table: TanstackTable) => JSX.Element } -export default function Table(props: Props) { +export default function Table(props: Props) { const [sorting, setSorting] = React.useState(props.initialSorting) const table = useReactTable({ @@ -83,48 +83,10 @@ export default function Table(props: Props) { ))} - {table.getRowModel().rows.map((row) => { - if (row.getIsExpanded()) { - return ( - - {getExpandedRowModel('farm', row, table.resetExpanded)} - - ) - } - - return getRowModel('farm', row, table.resetExpanded) - })} + {table.getRowModel().rows.map((row) => ( + + ))}
+
{status && } {status === VaultStatus.ACTIVE && } diff --git a/src/components/Earn/Lend/LendingMarketsTable.tsx b/src/components/Earn/Lend/LendingMarketsTable.tsx deleted file mode 100644 index 57f27a15..00000000 --- a/src/components/Earn/Lend/LendingMarketsTable.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { ColumnDef, Row, Table } from '@tanstack/react-table' -import { useCallback, useMemo } from 'react' - -import AmountAndValue from 'components/AmountAndValue' -import AssetImage from 'components/Asset/AssetImage' -import AssetRate from 'components/Asset/AssetRate' -import LendingActionButtons from 'components/Earn/Lend/LendingActionButtons' -import { FormattedNumber } from 'components/FormattedNumber' -import { ChevronDown, ChevronUp } from 'components/Icons' -import AssetListTable from 'components/MarketAssetTable' -import MarketAssetTableRow from 'components/MarketAssetTable/MarketAssetTableRow' -import MarketDetails from 'components/MarketAssetTable/MarketDetails' -import TitleAndSubCell from 'components/TitleAndSubCell' -import { BN_ZERO } from 'constants/math' -import { convertLiquidityRateToAPR } from 'utils/formatters' -import { BN } from 'utils/helpers' - -interface Props { - title: string - data: LendingMarketTableData[] -} - -export default function LendingMarketsTable(props: Props) { - const { title, data } = props - const shouldShowAccountDeposit = !!data[0]?.accountLentValue - - const rowRenderer = useCallback( - (row: Row, table: Table) => { - return ( - } - expandedDetails={} - /> - ) - }, - [], - ) - - const columns = useMemo[]>( - () => [ - { - accessorKey: 'asset.name', - header: 'Asset', - id: 'symbol', - cell: ({ row }) => { - const asset = row.original.asset - - return ( -
- - -
- ) - }, - }, - ...(shouldShowAccountDeposit - ? [ - { - accessorKey: 'accountDepositValue', - header: 'Deposited', - cell: ({ row }) => { - const amount = row.original.accountLentAmount - - return ( - - ) - }, - } as ColumnDef, - ] - : []), - { - accessorKey: 'marketLiquidityRate', - header: 'APR', - cell: ({ row }) => { - return ( - - ) - }, - }, - { - accessorKey: 'marketDepositCap', - header: 'Depo. Cap', - cell: ({ row }) => { - const { marketDepositCap, marketDepositAmount, asset } = row.original - const percent = marketDepositAmount - .dividedBy(row.original.marketDepositCap) - .multipliedBy(100) - - return ( - - } - sub={ - - } - /> - ) - }, - }, - { - accessorKey: 'manage', - enableSorting: false, - header: 'Manage', - cell: ({ row }) => ( -
-
{row.getIsExpanded() ? : }
-
- ), - }, - ], - [shouldShowAccountDeposit], - ) - - return -} diff --git a/src/components/Earn/Lend/Lends.tsx b/src/components/Earn/Lend/Lends.tsx new file mode 100644 index 00000000..ced4ab25 --- /dev/null +++ b/src/components/Earn/Lend/Lends.tsx @@ -0,0 +1,37 @@ +import React from 'react' + +import AvailableLendsTable from 'components/Earn/Lend/Table/AvailableLendsTable' +import DepositedLendsTable from 'components/Earn/Lend/Table/DepositedLendsTable' +import { BN_ZERO } from 'constants/math' +import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' +import { getLendEnabledAssets } from 'utils/assets' + +export default function Lends() { + const { accountLentAssets, availableAssets, allAssets } = useLendingMarketAssetsTableData() + + if (!allAssets?.length) { + return + } + return ( + <> + + + + ) +} + +function Fallback() { + const assets = getLendEnabledAssets() + const data: LendingMarketTableData[] = assets.map((asset) => ({ + asset, + marketDepositCap: BN_ZERO, + borrowEnabled: false, + marketMaxLtv: 0, + marketDepositAmount: BN_ZERO, + marketLiquidityRate: 0, + marketLiquidityAmount: BN_ZERO, + marketLiquidationThreshold: 0, + })) + + return +} diff --git a/src/components/Earn/Lend/Table/AvailableLendsTable.tsx b/src/components/Earn/Lend/Table/AvailableLendsTable.tsx new file mode 100644 index 00000000..02a34c35 --- /dev/null +++ b/src/components/Earn/Lend/Table/AvailableLendsTable.tsx @@ -0,0 +1,36 @@ +import { Row } from '@tanstack/react-table' +import React, { useCallback } from 'react' + +import Card from 'components/Card' +import { NAME_META } from 'components/Earn/Lend/Table/Columns/Name' +import useAvailableColumns from 'components/Earn/Lend/Table/Columns/useAvailableColumns' +import Table from 'components/Table' + +import MarketDetails from '../../../MarketDetails' + +type Props = { + data: LendingMarketTableData[] + isLoading: boolean +} + +export default function AvailableLendsTable(props: Props) { + const columns = useAvailableColumns({ isLoading: props.isLoading }) + + const renderExpanded = useCallback( + (row: Row) => , + [], + ) + + if (!props.data.length) return null + + return ( + + + + ) +} diff --git a/src/components/Earn/Lend/Table/Columns/Apr.tsx b/src/components/Earn/Lend/Table/Columns/Apr.tsx new file mode 100644 index 00000000..426f7c2a --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/Apr.tsx @@ -0,0 +1,26 @@ +import React from 'react' + +import AssetRate from 'components/Asset/AssetRate' +import Loading from 'components/Loading' +import { convertLiquidityRateToAPR } from 'utils/formatters' + +export const APR_META = { accessorKey: 'marketLiquidityRate', header: 'APR' } + +interface Props { + marketLiquidityRate: number + borrowEnabled: boolean + isLoading: boolean +} +export default function Apr(props: Props) { + if (props.isLoading) return + + return ( + + ) +} diff --git a/src/components/Earn/Lend/Table/Columns/DepositCap.tsx b/src/components/Earn/Lend/Table/Columns/DepositCap.tsx new file mode 100644 index 00000000..845ec0c4 --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/DepositCap.tsx @@ -0,0 +1,37 @@ +import React from 'react' + +import { FormattedNumber } from 'components/FormattedNumber' +import Loading from 'components/Loading' +import TitleAndSubCell from 'components/TitleAndSubCell' + +export const DEPOSIT_CAP_META = { accessorKey: 'marketDepositCap', header: 'Depo. Cap' } + +interface Props { + isLoading: boolean + data: LendingMarketTableData +} +export default function DepositCap(props: Props) { + if (props.isLoading) return + const { marketDepositCap, marketDepositAmount, asset } = props.data + const percent = marketDepositAmount.dividedBy(marketDepositCap).multipliedBy(100) + + return ( + + } + sub={ + + } + /> + ) +} diff --git a/src/components/Earn/Lend/Table/Columns/DepositValue.tsx b/src/components/Earn/Lend/Table/Columns/DepositValue.tsx new file mode 100644 index 00000000..5913703f --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/DepositValue.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +import AmountAndValue from 'components/AmountAndValue' +import { BN_ZERO } from 'constants/math' +import { BN } from 'utils/helpers' + +export const DEPOSIT_VALUE_META = { accessorKey: 'accountDepositValue', header: 'Deposited' } + +interface Props { + asset: Asset + lentAmount?: string +} +export default function DepositValue(props: Props) { + return ( + + ) +} diff --git a/src/components/Earn/Lend/Table/Columns/Manage.tsx b/src/components/Earn/Lend/Table/Columns/Manage.tsx new file mode 100644 index 00000000..3db5df17 --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/Manage.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +import { ChevronDown, ChevronUp } from 'components/Icons' + +export const MANAGE_META = { accessorKey: 'manage', enableSorting: false, header: 'Manage' } + +interface Props { + isExpanded: boolean +} +export default function Manage(props: Props) { + return ( +
+
{props.isExpanded ? : }
+
+ ) +} diff --git a/src/components/Earn/Lend/Table/Columns/Name.tsx b/src/components/Earn/Lend/Table/Columns/Name.tsx new file mode 100644 index 00000000..58de2e7f --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/Name.tsx @@ -0,0 +1,18 @@ +import React from 'react' + +import AssetImage from 'components/Asset/AssetImage' +import TitleAndSubCell from 'components/TitleAndSubCell' + +export const NAME_META = { accessorKey: 'asset.name', header: 'Asset', id: 'symbol' } +interface Props { + asset: Asset +} +export default function Name(props: Props) { + const { asset } = props + return ( +
+ + +
+ ) +} diff --git a/src/components/Earn/Lend/Table/Columns/useAvailableColumns.tsx b/src/components/Earn/Lend/Table/Columns/useAvailableColumns.tsx new file mode 100644 index 00000000..ac7199ad --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/useAvailableColumns.tsx @@ -0,0 +1,40 @@ +import { ColumnDef } from '@tanstack/react-table' +import { useMemo } from 'react' + +import Apr, { APR_META } from 'components/Earn/Lend/Table/Columns/Apr' +import DepositCap, { DEPOSIT_CAP_META } from 'components/Earn/Lend/Table/Columns/DepositCap' +import Manage, { MANAGE_META } from 'components/Earn/Lend/Table/Columns/Manage' +import Name, { NAME_META } from 'components/Earn/Lend/Table/Columns/Name' + +interface Props { + isLoading: boolean +} + +export default function useAvailableColumns(props: Props) { + return useMemo[]>(() => { + return [ + { + ...NAME_META, + cell: ({ row }) => , + }, + { + ...APR_META, + cell: ({ row }) => ( + + ), + }, + { + ...DEPOSIT_CAP_META, + cell: ({ row }) => , + }, + { + ...MANAGE_META, + cell: ({ row }) => , + }, + ] + }, []) +} diff --git a/src/components/Earn/Lend/Table/Columns/useDepositedColumns.tsx b/src/components/Earn/Lend/Table/Columns/useDepositedColumns.tsx new file mode 100644 index 00000000..5c14cbd4 --- /dev/null +++ b/src/components/Earn/Lend/Table/Columns/useDepositedColumns.tsx @@ -0,0 +1,47 @@ +import { ColumnDef } from '@tanstack/react-table' +import { useMemo } from 'react' + +import Apr, { APR_META } from 'components/Earn/Lend/Table/Columns/Apr' +import DepositCap, { DEPOSIT_CAP_META } from 'components/Earn/Lend/Table/Columns/DepositCap' +import DepositValue, { DEPOSIT_VALUE_META } from 'components/Earn/Lend/Table/Columns/DepositValue' +import Manage, { MANAGE_META } from 'components/Earn/Lend/Table/Columns/Manage' +import Name, { NAME_META } from 'components/Earn/Lend/Table/Columns/Name' + +interface Props { + isLoading: boolean +} + +export default function useDepositedColumns(props: Props) { + return useMemo[]>(() => { + return [ + { + ...NAME_META, + cell: ({ row }) => , + }, + { + ...DEPOSIT_VALUE_META, + cell: ({ row }) => ( + + ), + }, + { + ...APR_META, + cell: ({ row }) => ( + + ), + }, + { + ...DEPOSIT_CAP_META, + cell: ({ row }) => , + }, + { + ...MANAGE_META, + cell: ({ row }) => , + }, + ] + }, []) +} diff --git a/src/components/Earn/Lend/Table/DepositedLendsTable.tsx b/src/components/Earn/Lend/Table/DepositedLendsTable.tsx new file mode 100644 index 00000000..6ff03aa7 --- /dev/null +++ b/src/components/Earn/Lend/Table/DepositedLendsTable.tsx @@ -0,0 +1,35 @@ +import { Row } from '@tanstack/react-table' +import React, { useCallback } from 'react' + +import Card from 'components/Card' +import { NAME_META } from 'components/Earn/Lend/Table/Columns/Name' +import useDepositedColumns from 'components/Earn/Lend/Table/Columns/useDepositedColumns' +import MarketDetails from 'components/MarketDetails' +import Table from 'components/Table' + +type Props = { + data: LendingMarketTableData[] + isLoading: boolean +} + +export default function DepositedLendsTable(props: Props) { + const columns = useDepositedColumns({ isLoading: props.isLoading }) + + const renderExpanded = useCallback( + (row: Row) => , + [], + ) + + if (!props.data.length) return null + + return ( + +
+ + ) +} diff --git a/src/components/MarketAssetTable/MarketAssetTableRow.tsx b/src/components/MarketAssetTable/MarketAssetTableRow.tsx deleted file mode 100644 index 42ce6700..00000000 --- a/src/components/MarketAssetTable/MarketAssetTableRow.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { flexRender, Row } from '@tanstack/react-table' -import classNames from 'classnames' - -import Text from 'components/Text' - -type Props = { - rowData: Row - resetExpanded: (defaultState?: boolean | undefined) => void - isExpanded: boolean - expandedActionButtons?: JSX.Element - expandedDetails?: JSX.Element -} - -function AssetListTableRow(props: Props) { - const renderFullRow = (key: string, content: JSX.Element) => ( - - - - ) - - const renderExpanded = () => { - return ( - <> - {props.expandedActionButtons && - renderFullRow( - `${props.rowData.id}-expanded-actions`, -
- - Details - -
{props.expandedActionButtons}
-
, - )} - {props.expandedDetails && - renderFullRow(`${props.rowData.id}-expanded-details`, props.expandedDetails)} - - ) - } - - return ( - <> - { - const isExpanded = props.rowData.getIsExpanded() - props.resetExpanded() - !isExpanded && props.rowData.toggleExpanded() - }} - > - {props.rowData.getVisibleCells().map((cell) => { - return ( - - ) - })} - - {props.isExpanded && renderExpanded()} - - ) -} - -export default AssetListTableRow diff --git a/src/components/MarketAssetTable/index.tsx b/src/components/MarketAssetTable/index.tsx deleted file mode 100644 index c546b7bf..00000000 --- a/src/components/MarketAssetTable/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { - ColumnDef, - flexRender, - getCoreRowModel, - getSortedRowModel, - Row, - SortingState, - Table, - useReactTable, -} from '@tanstack/react-table' -import classNames from 'classnames' -import React from 'react' - -import Card from 'components/Card' -import { SortAsc, SortDesc, SortNone } from 'components/Icons' -import Text from 'components/Text' - -interface Props { - title: string - data: TData[] - columns: ColumnDef[] - sorting?: SortingState - rowRenderer: (row: Row, table: Table) => JSX.Element -} - -function AssetListTable(props: Props) { - const { title, data, columns } = props - const [sorting, setSorting] = React.useState(props.sorting ?? []) - - const table = useReactTable({ - data, - columns, - state: { - sorting, - }, - onSortingChange: setSorting, - getCoreRowModel: getCoreRowModel(), - getSortedRowModel: getSortedRowModel(), - }) - - const _rowRenderer = (row: Row) => props.rowRenderer(row, table) - - if (!data.length) return null - - return ( - -
- {content} -
- {flexRender(cell.column.columnDef.cell, cell.getContext())} -
- - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - ) - })} - - ))} - - {table.getRowModel().rows.map(_rowRenderer)} -
-
- - {header.column.getCanSort() - ? { - asc: , - desc: , - false: , - }[header.column.getIsSorted() as string] ?? null - : null} - - - {flexRender(header.column.columnDef.header, header.getContext())} - -
-
-
- ) -} - -export default AssetListTable diff --git a/src/components/MarketAssetTable/MarketDetails.tsx b/src/components/MarketDetails.tsx similarity index 79% rename from src/components/MarketAssetTable/MarketDetails.tsx rename to src/components/MarketDetails.tsx index 80340eb2..1f512b2e 100644 --- a/src/components/MarketAssetTable/MarketDetails.tsx +++ b/src/components/MarketDetails.tsx @@ -1,3 +1,4 @@ +import { Row } from '@tanstack/react-table' import { useMemo } from 'react' import { FormattedNumber } from 'components/FormattedNumber' @@ -5,7 +6,7 @@ import TitleAndSubCell from 'components/TitleAndSubCell' import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice' interface Props { - data: BorrowMarketTableData | LendingMarketTableData + row: Row type: 'borrow' | 'lend' } @@ -15,7 +16,7 @@ interface Detail { title: string } -export default function MarketDetails({ data, type }: Props) { +export default function MarketDetails({ row, type }: Props) { const { convertAmount, getConversionRate, @@ -28,7 +29,7 @@ export default function MarketDetails({ data, type }: Props) { marketDepositAmount, marketLiquidityAmount, marketLiquidationThreshold, - } = data + } = row.original const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount) @@ -36,7 +37,6 @@ export default function MarketDetails({ data, type }: Props) { const isDollar = displayCurrencySymbol === '$' function getLendingMarketDetails() { - const depositCap = (data as LendingMarketTableData).marketDepositCap return [ { amount: convertAmount(asset, marketDepositAmount).toNumber(), @@ -107,7 +107,6 @@ export default function MarketDetails({ data, type }: Props) { if (type === 'lend') return getLendingMarketDetails() return getBorrowMarketDetails() }, [ - data, type, asset, marketDepositAmount, @@ -120,23 +119,27 @@ export default function MarketDetails({ data, type }: Props) { ]) return ( -
- {details.map((detail, index) => ( - +
+
+ {details.map((detail, index) => ( + + } + sub={detail.title} /> - } - sub={detail.title} - /> - ))} -
+ ))} + +
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
) } - -function getExpandedRowModel( - type: 'farm', - row: unknown, - resetExpanded: (defaultState?: boolean | undefined) => void, -) { - switch (type) { - case 'farm': - return ( - <> - } resetExpanded={resetExpanded} /> - } resetExpanded={resetExpanded} /> - - ) - } -} - -function getRowModel( - type: 'farm', - row: Row, - resetExpanded: (defaultState?: boolean | undefined) => void, -) { - return ( - ).original.address} - row={row as Row} - resetExpanded={resetExpanded} - /> - ) -} diff --git a/src/components/Trade/AccountDetailsCard.tsx b/src/components/Trade/AccountDetailsCard.tsx index e3ca51a8..8a6d6831 100644 --- a/src/components/Trade/AccountDetailsCard.tsx +++ b/src/components/Trade/AccountDetailsCard.tsx @@ -8,14 +8,10 @@ import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableDa export default function AccountDetailsCard() { const account = useCurrentAccount() - const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } = - useBorrowMarketAssetsTableData() + const { data } = useBorrowMarketAssetsTableData(false) + const borrowAssetsData = useMemo(() => data?.allAssets || [], [data]) const { availableAssets: lendingAvailableAssets, accountLentAssets } = useLendingMarketAssetsTableData() - const borrowAssetsData = useMemo( - () => [...borrowAvailableAssets, ...accountBorrowedAssets], - [borrowAvailableAssets, accountBorrowedAssets], - ) const lendingAssetsData = useMemo( () => [...lendingAvailableAssets, ...accountLentAssets], [lendingAvailableAssets, accountLentAssets], diff --git a/src/constants/assets.ts b/src/constants/assets.ts index 061cba76..a3c364ff 100644 --- a/src/constants/assets.ts +++ b/src/constants/assets.ts @@ -17,6 +17,7 @@ export const ASSETS: Asset[] = [ logo: '/images/tokens/osmo.svg', isEnabled: true, isMarket: true, + isBorrowEnabled: true, isDisplayCurrency: true, isAutoLendEnabled: true, pythPriceFeedId: '5867f5683c757393a0670ef0f701490950fe93fdb006d181c8265a831ac0c5c6', @@ -38,6 +39,7 @@ export const ASSETS: Asset[] = [ isMarket: true, isDisplayCurrency: true, isAutoLendEnabled: true, + isBorrowEnabled: true, pythPriceFeedId: 'b00b60f88b03a6a625a8d1c048c3f66653edf217439983d037e7222c4e612819', poolId: 1, }, @@ -71,6 +73,7 @@ export const ASSETS: Asset[] = [ isMarket: ENV.NETWORK !== NETWORK.TESTNET, isDisplayCurrency: ENV.NETWORK !== NETWORK.TESTNET, isAutoLendEnabled: true, + isBorrowEnabled: true, pythPriceFeedId: 'e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43', poolId: 712, }, @@ -88,6 +91,7 @@ export const ASSETS: Asset[] = [ isMarket: ENV.NETWORK !== NETWORK.TESTNET, isDisplayCurrency: ENV.NETWORK !== NETWORK.TESTNET, isAutoLendEnabled: true, + isBorrowEnabled: true, pythPriceFeedId: 'ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace', poolId: 704, }, @@ -126,6 +130,7 @@ export const ASSETS: Asset[] = [ isMarket: true, isDisplayCurrency: true, isStable: true, + isBorrowEnabled: true, isAutoLendEnabled: true, pythPriceFeedId: 'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a', poolId: 678, diff --git a/src/hooks/useBorrowEnabledMarkets.ts b/src/hooks/useBorrowEnabledMarkets.ts new file mode 100644 index 00000000..27e1bc09 --- /dev/null +++ b/src/hooks/useBorrowEnabledMarkets.ts @@ -0,0 +1,6 @@ +import useMarketAssets from 'hooks/useMarketAssets' + +export default function useBorrowEnabledMarkets() { + const { data: markets } = useMarketAssets() + return markets.filter((market) => market.borrowEnabled) +} diff --git a/src/hooks/useBorrowMarketAssetsTableData.ts b/src/hooks/useBorrowMarketAssetsTableData.ts index e3019734..6d4f26d0 100644 --- a/src/hooks/useBorrowMarketAssetsTableData.ts +++ b/src/hooks/useBorrowMarketAssetsTableData.ts @@ -1,7 +1,6 @@ -import { useMemo } from 'react' +import useSWR from 'swr' import useCurrentAccountDebts from 'hooks/useCurrentAccountDebts' -import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets' import useMarketBorrowings from 'hooks/useMarketBorrowings' import useMarketDeposits from 'hooks/useMarketDeposits' import useMarketLiquidities from 'hooks/useMarketLiquidities' @@ -9,47 +8,55 @@ import { byDenom } from 'utils/array' import { getAssetByDenom } from 'utils/assets' import { BN } from 'utils/helpers' -export default function useBorrowMarketAssetsTableData(): { - accountBorrowedAssets: BorrowMarketTableData[] - availableAssets: BorrowMarketTableData[] - allAssets: BorrowMarketTableData[] -} { - const markets = useDepositEnabledMarkets() +import useBorrowEnabledMarkets from './useBorrowEnabledMarkets' + +export default function useBorrowMarketAssetsTableData(suspense = true) { + const markets = useBorrowEnabledMarkets() const accountDebts = useCurrentAccountDebts() const { data: borrowData } = useMarketBorrowings() const { data: marketDeposits } = useMarketDeposits() const { data: marketLiquidities } = useMarketLiquidities() - return useMemo(() => { - const accountBorrowedAssets: BorrowMarketTableData[] = [], - availableAssets: BorrowMarketTableData[] = [] + return useSWR( + 'borrowMarketAssetsTableData', + async (): Promise<{ + accountBorrowedAssets: BorrowMarketTableData[] + availableAssets: BorrowMarketTableData[] + allAssets: BorrowMarketTableData[] + }> => { + const accountBorrowedAssets: BorrowMarketTableData[] = [], + availableAssets: BorrowMarketTableData[] = [] - markets.forEach(({ denom, liquidityRate, liquidationThreshold, maxLtv }) => { - const asset = getAssetByDenom(denom) as Asset - const borrow = borrowData.find((borrow) => borrow.denom === denom) - const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0) - const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0) + markets.forEach(({ denom, liquidityRate, liquidationThreshold, maxLtv }) => { + const asset = getAssetByDenom(denom) as Asset + const borrow = borrowData.find((borrow) => borrow.denom === denom) + const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0) + const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0) - const debt = accountDebts?.find((debt) => debt.denom === denom) - if (!borrow) return + const debt = accountDebts?.find((debt) => debt.denom === denom) + if (!borrow) return - const borrowMarketAsset: BorrowMarketTableData = { - ...borrow, - asset, - debt: debt?.amount, - marketDepositAmount, - marketLiquidityAmount, - marketLiquidityRate: liquidityRate, - marketLiquidationThreshold: liquidationThreshold, - marketMaxLtv: maxLtv, + const borrowMarketAsset: BorrowMarketTableData = { + ...borrow, + asset, + debt: debt?.amount, + marketDepositAmount, + marketLiquidityAmount, + marketLiquidityRate: liquidityRate, + marketLiquidationThreshold: liquidationThreshold, + marketMaxLtv: maxLtv, + } + ;(borrowMarketAsset.debt ? accountBorrowedAssets : availableAssets).push(borrowMarketAsset) + }) + + return { + accountBorrowedAssets, + availableAssets, + allAssets: [...accountBorrowedAssets, ...availableAssets], } - ;(borrowMarketAsset.debt ? accountBorrowedAssets : availableAssets).push(borrowMarketAsset) - }) - - return { - accountBorrowedAssets, - availableAssets, - allAssets: [...accountBorrowedAssets, ...availableAssets], - } - }, [accountDebts, borrowData, markets, marketDeposits, marketLiquidities]) + }, + { + suspense, + }, + ) } diff --git a/src/pages/BorrowPage.tsx b/src/pages/BorrowPage.tsx index 97d65e2a..58ed4fe7 100644 --- a/src/pages/BorrowPage.tsx +++ b/src/pages/BorrowPage.tsx @@ -1,17 +1,13 @@ +import Borrowings from 'components/Borrow/Borrowings' import BorrowIntro from 'components/Borrow/BorrowIntro' -import BorrowTable from 'components/Borrow/BorrowTable' import MigrationBanner from 'components/MigrationBanner' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' export default function BorrowPage() { - const { accountBorrowedAssets, availableAssets } = useBorrowMarketAssetsTableData() - return (
- - +
) } diff --git a/src/pages/LendPage.tsx b/src/pages/LendPage.tsx index 0cce99ee..149ec560 100644 --- a/src/pages/LendPage.tsx +++ b/src/pages/LendPage.tsx @@ -1,19 +1,16 @@ -import LendingMarketsTable from 'components/Earn/Lend/LendingMarketsTable' import LendIntro from 'components/Earn/Lend/LendIntro' +import Lends from 'components/Earn/Lend/Lends' import Tab from 'components/Earn/Tab' import MigrationBanner from 'components/MigrationBanner' import { EARN_TABS } from 'constants/pages' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' export default function LendPage() { - const { accountLentAssets, availableAssets } = useLendingMarketAssetsTableData() return (
- - +
) } diff --git a/src/types/interfaces/asset.d.ts b/src/types/interfaces/asset.d.ts index b3ec19a3..e00b9446 100644 --- a/src/types/interfaces/asset.d.ts +++ b/src/types/interfaces/asset.d.ts @@ -50,6 +50,7 @@ interface Asset { isStable?: boolean isFavorite?: boolean isAutoLendEnabled?: boolean + isBorrowEnabled?: boolean pythPriceFeedId?: string forceFetchPrice?: boolean testnetDenom?: string diff --git a/src/utils/assets.ts b/src/utils/assets.ts index 0bb052c0..6d94714f 100644 --- a/src/utils/assets.ts +++ b/src/utils/assets.ts @@ -35,3 +35,7 @@ export function findCoinByDenom(denom: string, coins: BigNumberCoin[]) { export function getLendEnabledAssets() { return ASSETS.filter((asset) => asset.isAutoLendEnabled) } + +export function getBorrowEnabledAssets() { + return ASSETS.filter((asset) => asset.isBorrowEnabled) +}