Skip to content

Commit

Permalink
style(Balances): have a better overview for balances
Browse files Browse the repository at this point in the history
style(Balances): add skeletons for tables
feat(Pricing): add loading indicators for fetchin usdc price
fix(BentoBox): when withdrawing with max use shares instead of amounts
  • Loading branch information
chillichelli committed Feb 1, 2022
1 parent 1cf2324 commit 2bebe37
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 116 deletions.
4 changes: 2 additions & 2 deletions src/components/AssetInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 24,7 @@ import React, { createContext, FC, ReactNode, useContext, useEffect, useMemo, us
interface AssetInputProps {
value?: string
currency?: Currency
onChange: (x: string | undefined) => void
onChange: (x: string | undefined, max?: boolean) => void
spendFromWallet?: boolean
title?: string
onSelect?: (x: Token) => void
Expand Down Expand Up @@ -126,7 126,7 @@ const AssetInput: AssetInput<AssetInputProps> = ({
size={size}
currencyLogo={currencyLogo}
spendFromWallet={spendFromWallet}
onMax={() => props.onChange(maxSpend)}
onMax={() => props.onChange(maxSpend, true)}
showMax={
showMax && balance && maxSpendAsFraction && balance.greaterThan('0')
? !parsedInput?.equalTo(maxSpendAsFraction)
Expand Down
26 changes: 18 additions & 8 deletions src/features/trident/balances/ActionsModal/WithdrawView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 10,7 @@ import Typography from 'app/components/Typography'
import { useBalancesSelectedCurrency } from 'app/features/trident/balances/useBalancesDerivedState'
import { tryParseAmount } from 'app/functions'
import { useBentoBox } from 'app/hooks'
import useBentoRebases from 'app/hooks/useBentoRebases'
import { useActiveWeb3React } from 'app/services/web3'
import { useBentoBalanceV2 } from 'app/state/bentobox/hooks'
import { useCurrencyBalance } from 'app/state/wallet/hooks'
Expand All @@ -27,24 28,33 @@ const WithdrawView: FC<WithdrawViewProps> = ({ onClose, onBack }) => {
const walletBalance = useCurrencyBalance(account ?? undefined, currency)
const bentoBalance = useBentoBalanceV2(currency ? currency.wrapped.address : undefined)
const { withdraw } = useBentoBox()
const [value, setValue] = useState<string>()
const { rebases } = useBentoRebases([currency?.wrapped])
const [inputState, setInputState] = useState<{ value?: string; isMax: boolean }>({ value: undefined, isMax: false })
const { i18n } = useLingui()

const valueCA = currency ? tryParseAmount(value, currency) : undefined
const valueCA = currency ? tryParseAmount(inputState.value, currency) : undefined
let valuePlusBalance = valueCA?.wrapped
if (valuePlusBalance && walletBalance) valuePlusBalance = valuePlusBalance.wrapped.add(walletBalance.wrapped)

const execute = useCallback(async () => {
if (!currency || !value) return
if (!currency || !inputState.value) return

try {
setAttemptingTxn(true)
await withdraw(currency?.wrapped.address, value.toBigNumber(currency?.decimals))
if (inputState.isMax) {
await withdraw(
currency?.wrapped.address,
inputState.value.toBigNumber(currency?.decimals),
rebases?.[currency.wrapped.address]?.base
)
} else {
await withdraw(currency?.wrapped.address, inputState.value.toBigNumber(currency?.decimals))
}
} finally {
setAttemptingTxn(false)
onClose()
}
}, [currency, value, withdraw, onClose])
}, [currency, inputState.value, inputState.isMax, withdraw, rebases, onClose])

const error = !account
? i18n._(t`Connect Wallet`)
Expand All @@ -65,8 75,8 @@ const WithdrawView: FC<WithdrawViewProps> = ({ onClose, onBack }) => {
<AssetInput
title={''}
currency={currency}
onChange={(val) => setValue(val)}
value={value}
onChange={(val, isMax) => setInputState({ value: val, isMax: isMax || false })}
value={inputState.value}
spendFromWallet={false}
/>
<div className="z-10 flex justify-center -mt-6 -mb-6">
Expand All @@ -79,7 89,7 @@ const WithdrawView: FC<WithdrawViewProps> = ({ onClose, onBack }) => {
<WalletIcon width={20} height={20} />
</div>
<div className="flex flex-col gap-1">
<Typography variant="h3" className={value ? 'text-high-emphesis' : 'text-secondary'} weight={700}>
<Typography variant="h3" className={inputState.value ? 'text-high-emphesis' : 'text-secondary'} weight={700}>
{(valuePlusBalance || walletBalance)?.toSignificant(6)}
</Typography>
<Typography variant="xxs" className="text-secondary">
Expand Down
18 changes: 3 additions & 15 deletions src/features/trident/balances/AssetBalances/AssetBalances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 8,17 @@ import {
TABLE_TR_TH_CLASSNAME,
TABLE_WRAPPER_DIV_CLASSNAME,
} from 'app/features/trident/constants'
import { classNames } from 'app/functions'
import React, { FC } from 'react'
// @ts-ignore TYPE NEEDS FIXING
import { useFlexLayout, usePagination, useSortBy, useTable } from 'react-table'

interface AssetBalancesProps {
config: any
loading?: boolean
error?: boolean
selected?(row: any): boolean
onSelect?(row: any): void
}

const AssetBalances: FC<AssetBalancesProps> = ({ config, loading, error, onSelect, selected }) => {
const AssetBalances: FC<AssetBalancesProps> = ({ config, onSelect }) => {
const { i18n } = useLingui()

const {
Expand All @@ -33,7 31,7 @@ const AssetBalances: FC<AssetBalancesProps> = ({ config, loading, error, onSelec
} = useTable(config, useSortBy, usePagination, useFlexLayout)

return (
<div className={TABLE_WRAPPER_DIV_CLASSNAME}>
<div className={classNames(TABLE_WRAPPER_DIV_CLASSNAME, 'max-h-[800px] overflow-auto hide-scrollbar')}>
<table id="asset-balances-table" {...getTableProps()} className={TABLE_TABLE_CLASSNAME}>
<thead>
{headerGroups.map((headerGroup, i) => (
Expand All @@ -46,16 44,6 @@ const AssetBalances: FC<AssetBalancesProps> = ({ config, loading, error, onSelec
className={TABLE_TR_TH_CLASSNAME(i, headerGroup.headers.length)}
>
{column.render('Header')}
{i === 0 && (
<div className="inline-flex items-center">
<div
className={`animate-spin rounded-full h-4 w-4 border-t-2 border-b-2 border-blue inline-block ml-3 transition ${
loading ? 'opacity-100' : 'opacity-0'
}`}
/>
{error && <span className="ml-2 text-sm italic text-red">{i18n._(t`⚠️ Loading Error`)}</span>}
</div>
)}
</th>
))}
</tr>
Expand Down
40 changes: 15 additions & 25 deletions src/features/trident/balances/AssetBalances/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 6,33 @@ import AssetBalances from 'app/features/trident/balances/AssetBalances/AssetBala
import { Assets } from 'app/features/trident/balances/AssetBalances/types'
import { useLPTableConfig } from 'app/features/trident/balances/AssetBalances/useLPTableConfig'
import { setBalancesState } from 'app/features/trident/balances/balancesSlice'
import { useBalancesSelectedCurrency } from 'app/features/trident/balances/useBalancesDerivedState'
import { ActiveModal } from 'app/features/trident/types'
import { useTridentLiquidityPositions } from 'app/services/graph'
import { useActiveWeb3React } from 'app/services/web3'
import { useBentoBalancesV2 } from 'app/state/bentobox/hooks'
import { useAppDispatch } from 'app/state/hooks'
import { useAllTokenBalances, useCurrencyBalance } from 'app/state/wallet/hooks'
import { useAllTokenBalancesWithLoadingIndicator, useCurrencyBalance } from 'app/state/wallet/hooks'
import React, { useCallback, useMemo } from 'react'

import { useTableConfig } from './useTableConfig'

export const LiquidityPositionsBalances = () => {
const { account, chainId } = useActiveWeb3React()

const {
data: positions,
isValidating,
error,
} = useTridentLiquidityPositions({
const { data: positions } = useTridentLiquidityPositions({
chainId,
variables: { where: { user: account?.toLowerCase(), balance_gt: 0 } },
shouldFetch: !!chainId && !!account,
})

const { config } = useLPTableConfig(positions)
return <AssetBalances config={config} loading={isValidating} error={error} />
return <AssetBalances config={config} />
}

export const BentoBalances = () => {
const { account } = useActiveWeb3React()
const { i18n } = useLingui()
const dispatch = useAppDispatch()
const selected = useBalancesSelectedCurrency()
const balances = useBentoBalancesV2()
const assets = balances.reduce<Assets[]>((acc, el) => {
if (el) acc.push({ asset: el })
Expand All @@ -57,16 52,14 @@ export const BentoBalances = () => {
[dispatch]
)

const { config } = useTableConfig(assets)
const { config } = useTableConfig(assets, balances.length === 0 && !!account)

return (
<div className="flex flex-col gap-3">
<Typography className="text-high-emphesis">{i18n._(t`BentoBox`)}</Typography>
<AssetBalances
config={config}
selected={(row) => row.values.asset.currency === selected}
onSelect={handleRowClick}
/>
<Typography weight={700} variant="lg" className="px-2 text-high-emphesis">
{i18n._(t`BentoBox`)}
</Typography>
<AssetBalances config={config} onSelect={handleRowClick} />
</div>
)
}
Expand All @@ -75,9 68,8 @@ export const WalletBalances = () => {
const { i18n } = useLingui()
const { chainId, account } = useActiveWeb3React()
const dispatch = useAppDispatch()
const selected = useBalancesSelectedCurrency()
const [_balances, loading] = useAllTokenBalancesWithLoadingIndicator()

const _balances = useAllTokenBalances()
// @ts-ignore TYPE NEEDS FIXING
const ethBalance = useCurrencyBalance(account ? account : undefined, chainId ? NATIVE[chainId] : undefined)

Expand All @@ -93,7 85,7 @@ export const WalletBalances = () => {
}
return res
}, [_balances, ethBalance])
const { config } = useTableConfig(balances)
const { config } = useTableConfig(balances, loading)

const handleRowClick = useCallback(
(row) => {
Expand All @@ -110,12 102,10 @@ export const WalletBalances = () => {

return (
<div className="flex flex-col gap-3">
<Typography className="text-high-emphesis">{i18n._(t`Wallet`)}</Typography>
<AssetBalances
config={config}
selected={(row) => row.values.asset.currency === selected}
onSelect={handleRowClick}
/>
<Typography weight={700} variant="lg" className="px-2 text-high-emphesis">
{i18n._(t`Wallet`)}
</Typography>
<AssetBalances config={config} onSelect={handleRowClick} />
</div>
)
}
97 changes: 53 additions & 44 deletions src/features/trident/balances/AssetBalances/useTableConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 2,10 @@ import { CurrencyLogo } from 'app/components/CurrencyLogo'
import Typography from 'app/components/Typography'
import { Assets } from 'app/features/trident/balances/AssetBalances/types'
import { currencyFormatter } from 'app/functions'
import useDesktopMediaQuery from 'app/hooks/useDesktopMediaQuery'
import { useUSDCValue } from 'app/hooks/useUSDCPrice'
import { useUSDCPriceWithLoadingIndicator, useUSDCValueWithLoadingIndicator } from 'app/hooks/useUSDCPrice'
import React, { useMemo } from 'react'

export const useTableConfig = (assets?: Assets[]) => {
const isDesktop = useDesktopMediaQuery()
export const useTableConfig = (assets?: Assets[], balancesLoading?: boolean) => {
const AssetColumns = useMemo(
() => [
{
Expand All @@ -18,39 16,38 @@ export const useTableConfig = (assets?: Assets[]) => {
className: 'text-left',
// @ts-ignore TYPE NEEDS FIXING
Cell: (props) => {
return (
<div className="flex gap-2.5 items-center">
<CurrencyLogo currency={props.cell.value.currency} className="!rounded-full" size={28} />
<Typography
weight={isDesktop ? 400 : 700}
variant={isDesktop ? 'sm' : 'base'}
className="text-left text-high-emphesis"
>
{props.cell.value.currency.symbol}
</Typography>
</div>
const { price, loading } = useUSDCPriceWithLoadingIndicator(
balancesLoading ? undefined : props.cell.value.currency
)
},
},
{
id: 'balance',
Header: 'Balance',
accessor: 'asset',
maxWidth: 100,
className: 'text-left',
// @ts-ignore TYPE NEEDS FIXING
Cell: (props) => {

if (loading || balancesLoading) {
return (
<div className="flex gap-2.5 items-center w-full h-10">
<div className="bg-dark-800 rounded-full w-9 h-9 animate-pulse" />
<div className="flex flex-col gap-1.5">
<div className="h-4 bg-dark-700 rounded animate-pulse w-[50px]" />
<div className="h-2 bg-dark-800 rounded animate-pulse w-[50px]" />
</div>
</div>
)
}

return (
<Typography
weight={isDesktop ? 400 : 700}
variant={isDesktop ? 'sm' : 'base'}
className="text-left text-high-emphesis"
>
{props.cell.value.toSignificant(6)}
</Typography>
<div className="flex gap-2.5 items-center h-10">
<CurrencyLogo currency={props.cell.value.currency} className="!rounded-full" size={36} />
<div className="flex flex-col">
<Typography weight={700} className="text-left text-high-emphesis">
{props.cell.value.currency.symbol}
</Typography>
{price && (
<Typography weight={400} variant="sm" className="text-left text-low-emphesis">
{currencyFormatter.format(Number(price?.toFixed()))}
</Typography>
)}
</div>
</div>
)
},
cellClassName: '',
},
{
id: 'value',
Expand All @@ -60,20 57,32 @@ export const useTableConfig = (assets?: Assets[]) => {
className: 'text-right flex justify-end',
// @ts-ignore TYPE NEEDS FIXING
Cell: (props) => {
const usdcValue = useUSDCValue(props.cell.value)
const { value, loading } = useUSDCValueWithLoadingIndicator(balancesLoading ? undefined : props.cell.value)
if (loading || balancesLoading) {
return (
<div className="flex gap-2.5 items-center justify-end w-full">
<div className="flex flex-col gap-1.5">
<div className="h-4 bg-dark-700 rounded animate-pulse w-[50px]" />
<div className="h-2 bg-dark-800 rounded animate-pulse w-[50px]" />
</div>
</div>
)
}

return (
<Typography
weight={700}
variant={isDesktop ? 'sm' : 'base'}
className="w-full text-right text-high-emphesis"
>
{usdcValue ? `${currencyFormatter.format(Number(usdcValue.toExact()))}` : '-'}
</Typography>
<div className="flex flex-col">
<Typography weight={700} className="w-full text-right text-high-emphesis">
{value ? `${currencyFormatter.format(Number(value.toExact()))}` : '-'}
</Typography>
<Typography weight={400} variant="sm" className="text-right text-low-emphesis">
{props.cell.value.toSignificant(6)}
</Typography>
</div>
)
},
},
],
[isDesktop]
[balancesLoading]
)

const defaultColumn = React.useMemo(() => ({ minWidth: 0 }), [])
Expand All @@ -82,14 91,14 @@ export const useTableConfig = (assets?: Assets[]) => {
() => ({
config: {
columns: AssetColumns,
data: assets,
data: balancesLoading ? new Array(5).fill({ asset: undefined }) : assets,
defaultColumn,
initialState: {
sortBy: [{ id: 'value', desc: true }],
},
manualPagination: true,
},
}),
[AssetColumns, assets, defaultColumn]
[AssetColumns, assets, balancesLoading, defaultColumn]
)
}
Loading

0 comments on commit 2bebe37

Please sign in to comment.