Skip to content

Commit

Permalink
Merge pull request #1398 from oasisprotocol/csillag/named-accounts-on…
Browse files Browse the repository at this point in the history
…-oasis

Add named accounts
  • Loading branch information
csillag authored May 22, 2024
2 parents 9a28cd7 + a59aae3 commit 728cf80
Show file tree
Hide file tree
Showing 25 changed files with 594 additions and 46 deletions.
1 change: 1 addition & 0 deletions .changelog/1398.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Initial support for named accounts
71 changes: 60 additions & 11 deletions src/app/components/Account/AccountLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import { RouteUtils } from '../../utils/route-utils'
import InfoIcon from '@mui/icons-material/Info'
import Typography from '@mui/material/Typography'
import { SearchScope } from '../../../types/searchScope'
import { useAccountMetadata } from '../../hooks/useAccountMetadata'
import { trimLongString } from '../../utils/trimLongString'
import { MaybeWithTooltip } from '../AdaptiveTrimmer/MaybeWithTooltip'
import Box from '@mui/material/Box'
import { HighlightedText } from '../HighlightedText'
import { AdaptiveHighlightedText } from '../HighlightedText/AdaptiveHighlightedText'
import { AdaptiveTrimmer } from '../AdaptiveTrimmer/AdaptiveTrimmer'

const WithTypographyAndLink: FC<{
Expand All @@ -24,7 +28,7 @@ const WithTypographyAndLink: FC<{
...(mobile
? {
maxWidth: '100%',
overflowX: 'hidden',
overflow: 'hidden',
}
: {}),
}}
Expand Down Expand Up @@ -52,7 +56,12 @@ interface Props {
/**
* Should we always trim the text to a short line when on mobile or Tablet?
*/
alwaysTrimOnTable?: boolean
alwaysTrimOnTablet?: boolean

/**
* What part of the name should be highlighted (if any)
*/
highlightedPartOfName?: string | undefined

/**
* Any extra tooltips to display
Expand All @@ -73,47 +82,87 @@ export const AccountLink: FC<Props> = ({
scope,
address,
alwaysTrim,
alwaysTrimOnTable,
alwaysTrimOnTablet,
highlightedPartOfName,
extraTooltip,
labelOnly,
}) => {
const { isTablet } = useScreenSize()
const {
metadata: accountMetadata,
// isError, // Use this to indicate that we have failed to load the name for this account
} = useAccountMetadata(scope, address)
const accountName = accountMetadata?.name // TODO: we should also use the description

const to = RouteUtils.getAccountRoute(scope, address)

const extraTooltipWithIcon = extraTooltip ? (
<>
<Box
sx={{
display: 'inline-flex',
alignItems: 'center',
verticalAlign: 'middle',
gap: 2,
}}
>
<InfoIcon />
{extraTooltip}
</>
</Box>
) : undefined

// Are we in a situation when we should always trim?
if (alwaysTrim || (alwaysTrimOnTable && isTablet)) {
if (alwaysTrim || (alwaysTrimOnTablet && isTablet)) {
// In a table, we only ever want a short line

return (
<WithTypographyAndLink to={to} labelOnly={labelOnly}>
<MaybeWithTooltip title={address}>{trimLongString(address, 6, 6)}</MaybeWithTooltip>
<MaybeWithTooltip
title={
<div>
{accountName && <Box sx={{ fontWeight: 'bold' }}>{accountName}</Box>}
<Box sx={{ fontWeight: 'normal' }}>{address}</Box>
{extraTooltipWithIcon}
</div>
}
>
{accountName ? trimLongString(accountName, 12, 0) : trimLongString(address, 6, 6)}
</MaybeWithTooltip>
</WithTypographyAndLink>
)
}

if (!isTablet) {
// Details in desktop mode.
// We want one long line
// We want one long line, with name and address.

return (
<WithTypographyAndLink to={to} labelOnly={labelOnly}>
<MaybeWithTooltip title={extraTooltipWithIcon}>{address} </MaybeWithTooltip>
<MaybeWithTooltip title={extraTooltipWithIcon}>
{accountName ? (
<span>
<HighlightedText text={accountName} pattern={highlightedPartOfName} /> ({address})
</span>
) : (
address
)}
</MaybeWithTooltip>
</WithTypographyAndLink>
)
}

// We need to show the data in details mode on mobile.
// Line adaptively shortened to fill available space
// We want two lines, one for name (if available), one for address
// Both lines adaptively shortened to fill available space
return (
<WithTypographyAndLink to={to} mobile labelOnly={labelOnly}>
<AdaptiveTrimmer text={address} strategy="middle" extraTooltip={extraTooltip} />
<>
<AdaptiveHighlightedText
text={accountName}
pattern={highlightedPartOfName}
extraTooltip={extraTooltip}
/>
<AdaptiveTrimmer text={address} strategy="middle" extraTooltip={extraTooltip} />
</>
</WithTypographyAndLink>
)
}
12 changes: 10 additions & 2 deletions src/app/components/Account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type RuntimeAccountDataProps = {
isLoading: boolean
tokenPrices: AllTokenPrices
showLayer?: boolean
highlightedPartOfName: string | undefined
}

export const RuntimeAccountData: FC<RuntimeAccountDataProps> = ({
Expand All @@ -41,6 +42,7 @@ export const RuntimeAccountData: FC<RuntimeAccountDataProps> = ({
isLoading,
tokenPrices,
showLayer,
highlightedPartOfName,
}) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
Expand Down Expand Up @@ -76,7 +78,7 @@ export const RuntimeAccountData: FC<RuntimeAccountDataProps> = ({
<AccountAvatar account={account} />
</StyledListTitleWithAvatar>
<dd>
<AccountLink scope={account} address={address!} />
<AccountLink scope={account} address={address!} highlightedPartOfName={highlightedPartOfName} />
<CopyToClipboard value={address!} />
</dd>

Expand Down Expand Up @@ -175,13 +177,15 @@ export type ConsensusAccountDataProps = {
isLoading?: boolean
showLayer?: boolean
standalone?: boolean
highlightedPartOfName?: string | undefined
}

export const ConsensusAccountData: FC<ConsensusAccountDataProps> = ({
account,
isLoading,
showLayer,
standalone,
highlightedPartOfName,
}) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
Expand All @@ -205,7 +209,11 @@ export const ConsensusAccountData: FC<ConsensusAccountDataProps> = ({
</Box>
</StyledListTitleWithAvatar>
<dd>
<AccountLink scope={account} address={account.address} />
<AccountLink
scope={account}
address={account.address}
highlightedPartOfName={highlightedPartOfName}
/>
<CopyToClipboard value={account.address} />
</dd>
<dt>
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/RuntimeEvents/RuntimeEventDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const EvmEventParamData: FC<{
// TODO: handle more EVM types
case 'address':
return address ? (
<AccountLink address={address} scope={scope} alwaysTrimOnTable={alwaysTrimOnTable} />
<AccountLink address={address} scope={scope} alwaysTrimOnTablet={alwaysTrimOnTable} />
) : null
case 'uint256':
// TODO: format with BigNumber
Expand Down
5 changes: 5 additions & 0 deletions src/app/components/Search/search-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ export const validateAndNormalize = {
return searchTerm.toLowerCase()
}
},
accountNameFragment: (searchTerm: string) => {
if (searchTerm?.length >= textSearchMininumLength) {
return searchTerm.toLowerCase()
}
},
} satisfies { [name: string]: (searchTerm: string) => string | undefined }

export function isSearchValid(searchTerm: string) {
Expand Down
51 changes: 51 additions & 0 deletions src/app/data/named-accounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Network } from '../../types/network'
import { Account, Layer, Runtime, RuntimeAccount } from '../../oasis-nexus/api'

export type AccountMetadata = {
address: string
name?: string
description?: string
}

export type AccountMetadataInfo = {
metadata?: AccountMetadata
isLoading: boolean
isError: boolean
}

export type AccountMap = Map<string, AccountMetadata>

export type AccountData = {
map: AccountMap
list: AccountMetadata[]
}

export type AccountNameSearchMatch = {
network: Network
layer: Layer
address: string
}

export type AccountNameSearchRuntimeMatch = {
network: Network
layer: Runtime
address: string
}

export type AccountNameSearchConsensusMatch = {
network: Network
layer: typeof Layer.consensus
address: string
}

export type AccountNameSearchResults = {
results: (Account | RuntimeAccount)[] | undefined
isLoading: boolean
isError: boolean
}

export type AccountNameSearchRuntimeResults = {
results: RuntimeAccount[] | undefined
isLoading: boolean
isError: boolean
}
Loading

0 comments on commit 728cf80

Please sign in to comment.