Skip to content

Commit

Permalink
Merge pull request #1423 from oasisprotocol/csillag/consensus-account…
Browse files Browse the repository at this point in the history
…-fixup

Consensus account fixup
  • Loading branch information
csillag authored May 22, 2024
2 parents b8610d9 + 87d9097 commit 65efc51
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 331 deletions.
2 changes: 2 additions & 0 deletions .changelog/1423.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Follow-up / clean-up after #1422
Support searching for consensus accounts (by address)
109 changes: 109 additions & 0 deletions src/app/components/Account/ConsensusAccountDetailsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { CardEmptyState } from '../CardEmptyState'
import { Account } from '../../../oasis-nexus/api'
import { useScreenSize } from '../../hooks/useScreensize'
import { TextSkeleton } from '../Skeleton'
import { StyledDescriptionList, StyledListTitleWithAvatar } from '../StyledDescriptionList'
import { DashboardLink } from '../../pages/ParatimeDashboardPage/DashboardLink'
import Box from '@mui/material/Box'
import { styled } from '@mui/material/styles'
import { AccountAvatar } from '../AccountAvatar'
import { AccountSizeBadge } from '../AccountSizeBadge'
import { AccountLink } from './AccountLink'
import { CopyToClipboard } from '../CopyToClipboard'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

export const StyledListTitle = styled('dt')(({ theme }) => ({
marginLeft: theme.spacing(4),
}))

type ConsensusAccountDetailsViewProps = {
account?: Account
isError?: boolean
isLoading?: boolean
showLayer?: boolean
standalone?: boolean
highlightedPartOfName?: string
}

export const ConsensusAccountDetailsView: FC<ConsensusAccountDetailsViewProps> = ({
account,
isError,
isLoading,
showLayer,
standalone,
highlightedPartOfName,
}) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()

if (isLoading) return <TextSkeleton numberOfRows={7} />
if (isError || !account) return <CardEmptyState label={t('account.cantLoadDetails')} />

return (
<StyledDescriptionList titleWidth={isMobile ? '160px' : '200px'} standalone={standalone}>
{showLayer && (
<>
<dt>{t('common.layer')}</dt>
<dd>
<DashboardLink scope={account} />
</dd>
</>
)}
<StyledListTitleWithAvatar>
<Box gap={1} sx={{ display: 'flex', alignItems: 'center' }}>
<AccountAvatar account={account} />
<AccountSizeBadge size={account.size} />
</Box>
</StyledListTitleWithAvatar>
<dd>
<AccountLink
scope={account}
address={account.address}
highlightedPartOfName={highlightedPartOfName}
/>
<CopyToClipboard value={account.address} />
</dd>
<dt>
<strong>{t('account.totalBalance')}</strong>
</dt>
<dd>
<strong>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.total),
ticker: account.ticker,
})}
</strong>
</dd>
<StyledListTitle>{t('account.available')}</StyledListTitle>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.available),
ticker: account.ticker,
})}
</dd>
<StyledListTitle>{t('common.staking')}</StyledListTitle>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.delegations_balance!),
ticker: account.ticker,
})}
</dd>
<StyledListTitle>{t('account.debonding')}</StyledListTitle>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.debonding_delegations_balance!),
ticker: account.ticker,
})}
</dd>
<dt>{t('account.lastNonce')}</dt>
<dd>{account.nonce}</dd>
<dt>{t('account.birth')}</dt>
<dd>
{/* TODO: provide date when it is implemented in the API */}
<>-</>
</dd>
</StyledDescriptionList>
)
}
170 changes: 170 additions & 0 deletions src/app/components/Account/RuntimeAccountDetailsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { Link as RouterLink } from 'react-router-dom'
import { useScreenSize } from '../../hooks/useScreensize'
import { StyledDescriptionList, StyledListTitleWithAvatar } from '../../components/StyledDescriptionList'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { TextSkeleton } from '../../components/Skeleton'
import { EvmToken, type RuntimeAccount } from '../../../oasis-nexus/api'
import { TokenPills } from './TokenPills'
import { AccountLink } from './AccountLink'
import { RouteUtils } from '../../utils/route-utils'
import { accountTransactionsContainerId } from '../../pages/RuntimeAccountDetailsPage/AccountTransactionsCard'
import Link from '@mui/material/Link'
import { DashboardLink } from '../../pages/ParatimeDashboardPage/DashboardLink'
import { getNameForTicker } from '../../../types/ticker'
import { AllTokenPrices } from '../../../coin-gecko/api'
import { ContractCreatorInfo } from './ContractCreatorInfo'
import { ContractVerificationIcon } from '../ContractVerificationIcon'
import { TokenLink } from '../Tokens/TokenLink'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'
import { AccountAvatar } from '../AccountAvatar'
import { RuntimeBalanceDisplay } from '../Balance/RuntimeBalanceDisplay'
import { calculateFiatValue } from '../Balance/hooks'
import { FiatMoneyAmount } from '../Balance/FiatMoneyAmount'
import { getFiatCurrencyForScope, getTokensForScope, showFiatValues } from '../../../config'
import { CardEmptyState } from '../CardEmptyState'

type RuntimeAccountDetailsViewProps = {
isLoading?: boolean
isError?: boolean
account?: RuntimeAccount
token?: EvmToken
tokenPrices: AllTokenPrices
showLayer?: boolean
highlightedPartOfName?: string
}

export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
account,
token,
isLoading,
isError,
tokenPrices,
showLayer,
highlightedPartOfName,
}) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()

if (isLoading) return <TextSkeleton numberOfRows={8} />
if (isError || !account) return <CardEmptyState label={t('account.cantLoadDetails')} />

const address = account.address_eth ?? account.address

const transactionsLabel = account.stats.num_txns.toLocaleString()
const transactionsAnchor = `${RouteUtils.getAccountRoute(
account,
account.address_eth ?? account.address,
)}#${accountTransactionsContainerId}`

const nativeTokens = getTokensForScope(account)
const nativeTickerNames = nativeTokens.map(token => getNameForTicker(t, token.ticker))
const contract = account?.evm_contract
const fiatValueInfo = calculateFiatValue(account?.balances, tokenPrices, getFiatCurrencyForScope(account))

return (
<StyledDescriptionList titleWidth={isMobile ? '100px' : '200px'}>
{showLayer && (
<>
<dt>{t('common.paratime')}</dt>
<dd>
<DashboardLink scope={account} />
</dd>
</>
)}
<StyledListTitleWithAvatar>
<AccountAvatar account={account} />
</StyledListTitleWithAvatar>
<dd>
<AccountLink scope={account} address={address!} highlightedPartOfName={highlightedPartOfName} />
<CopyToClipboard value={address!} />
</dd>

{token && (
<>
<dt>{t('common.token')}</dt>
<dd>
<TokenLink
scope={account}
address={token.eth_contract_addr || token.contract_addr}
name={token.name}
/>
</dd>
</>
)}

{contract && (
<>
<dt>{t('contract.verification.title')}</dt>
<dd>
<ContractVerificationIcon account={account} />
</dd>
</>
)}

{contract && (
<>
<dt>{t('contract.creator')}</dt>
<dd>
<ContractCreatorInfo
scope={account}
creationTxHash={contract.eth_creation_tx || contract.creation_tx}
alwaysTrim
/>
</dd>
</>
)}

<dt>{t('common.balance')}</dt>
<dd>
<RuntimeBalanceDisplay balances={account.balances} />
</dd>

<dt>{t('common.tokens')}</dt>
<dd>
<TokenPills account={account} tokens={account.evm_balances} />
</dd>

{showFiatValues && !fiatValueInfo.loading && fiatValueInfo.hasValue && (
<>
<dt>{t('common.fiatValue')}</dt>
<dd>
<FiatMoneyAmount {...fiatValueInfo} />
</dd>
</>
)}

<dt>{t('common.transactions')}</dt>
<dd>
{account.stats.num_txns ? (
<Link component={RouterLink} to={transactionsAnchor!}>
{transactionsLabel}
</Link>
) : (
transactionsLabel
)}
</dd>

{nativeTokens.length === 1 && (
<>
<dt>{t('account.totalReceived')}</dt>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.stats.total_received),
ticker: nativeTickerNames[0],
})}
</dd>

<dt>{t('account.totalSent')}</dt>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.stats.total_sent),
ticker: nativeTickerNames[0],
})}
</dd>
</>
)}
</StyledDescriptionList>
)
}
Loading

0 comments on commit 65efc51

Please sign in to comment.