Skip to content

Commit 6758623

Browse files
authored
Merge pull request #2311 from oasisprotocol/lw/balance-on-other-layers
Show balances of same account on other paratimes/consensus
2 parents 214dbac + 16756ca commit 6758623

11 files changed

Lines changed: 129 additions & 31 deletions

File tree

.changelog/2311.bugfix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Show "Balance: 0 ROSE" on Sapphire instead of "Balance: n/a"

.changelog/2311.feature.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Show balances of same account on other paratimes/consensus
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { FC } from 'react'
2+
import { useTranslation } from 'react-i18next'
3+
import {
4+
Account,
5+
isAccountEmpty,
6+
RuntimeAccount,
7+
useGetConsensusAccountsAddress,
8+
useGetRuntimeAccountsAddress,
9+
} from '../../../oasis-nexus/api'
10+
import { getLayerLabels } from '../../utils/content'
11+
import { RouteUtils } from '../../utils/route-utils'
12+
import { Link as RouterLink } from 'react-router-dom'
13+
import { Link } from '@oasisprotocol/ui-library/src/components/link'
14+
import { Tooltip } from '@oasisprotocol/ui-library/src/components/tooltip'
15+
import { RuntimeBalanceDisplay } from '../Balance/RuntimeBalanceDisplay'
16+
import { RoundedBalance } from '../RoundedBalance'
17+
18+
/** Ignoring pontus-x and cipher */
19+
export const BalancesOnOtherLayers: FC<{ account: Account | RuntimeAccount }> = ({ account }) => {
20+
const { t } = useTranslation()
21+
const layerLabels = getLayerLabels(t)
22+
23+
const queries = [
24+
useGetConsensusAccountsAddress(account.network, account.address),
25+
useGetRuntimeAccountsAddress(account.network, 'sapphire', account.address),
26+
useGetRuntimeAccountsAddress(account.network, 'emerald', account.address),
27+
]
28+
29+
const activeOnLayers = queries
30+
.filter(query => query.data?.data.layer !== account.layer)
31+
.filter(query => query.data?.data && !isAccountEmpty(query.data.data))
32+
.map((query, i) => {
33+
const account = query.data!.data
34+
35+
// TODO: switch both to totalBalance when runtime API returns it
36+
const printBalance =
37+
account.layer === 'consensus' ? (
38+
<>
39+
{t('account.totalBalance')}: <RoundedBalance value={account.total} ticker={account.ticker} />
40+
</>
41+
) : (
42+
<>
43+
{t('account.availableBalance')}:{' '}
44+
<RuntimeBalanceDisplay balances={account.balances} scope={account} className="inline-block" />
45+
</>
46+
)
47+
48+
return (
49+
<span key={account.layer}>
50+
{i > 0 && ' and '}
51+
52+
<Tooltip title={printBalance}>
53+
<Link asChild className="font-medium">
54+
<RouterLink
55+
to={RouteUtils.getAccountRoute(
56+
account,
57+
(account as RuntimeAccount).address_eth ?? account.address,
58+
)}
59+
>
60+
{layerLabels[account.layer]}
61+
</RouterLink>
62+
</Link>
63+
</Tooltip>
64+
</span>
65+
)
66+
})
67+
68+
if (activeOnLayers.length <= 0) return null
69+
70+
return (
71+
<span className="text-muted-foreground">
72+
&nbsp; ({`${t('account.hasBalancesOnOtherLayers')} `} {activeOnLayers})
73+
</span>
74+
)
75+
}

src/app/components/Account/ConsensusAccountDetailsView.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Link } from '@oasisprotocol/ui-library/src/components/link'
1616
import { RouteUtils } from '../../utils/route-utils'
1717
import { transactionsContainerId } from '../../utils/tabAnchors'
1818
import { RoundedBalance } from '../RoundedBalance'
19+
import { BalancesOnOtherLayers } from './BalancesOnOtherLayers'
1920

2021
export const StyledListTitle = styled('dt')(({ theme }) => ({
2122
marginLeft: theme.spacing(4),
@@ -27,6 +28,7 @@ type ConsensusAccountDetailsViewProps = {
2728
isLoading?: boolean
2829
showLayer?: boolean
2930
standalone?: boolean
31+
showBalancesOnOtherLayers?: boolean
3032
}
3133

3234
export const ConsensusAccountDetailsView: FC<ConsensusAccountDetailsViewProps> = ({
@@ -35,6 +37,7 @@ export const ConsensusAccountDetailsView: FC<ConsensusAccountDetailsViewProps> =
3537
isLoading,
3638
showLayer,
3739
standalone,
40+
showBalancesOnOtherLayers,
3841
}) => {
3942
const { t } = useTranslation()
4043
const formattedFirstActivity = useFormattedTimestampStringWithDistance(account?.first_activity)
@@ -52,14 +55,6 @@ export const ConsensusAccountDetailsView: FC<ConsensusAccountDetailsViewProps> =
5255
className="grid-cols-[160px_auto] sm:grid-cols-[200px_auto]"
5356
standalone={standalone}
5457
>
55-
{showLayer && (
56-
<>
57-
<dt>{t('common.layer')}</dt>
58-
<dd>
59-
<DashboardLink scope={account} />
60-
</dd>
61-
</>
62-
)}
6358
<StyledListTitleWithAvatar>
6459
<div className="flex items-center gap-1">
6560
<AccountAvatar account={account} />
@@ -72,6 +67,15 @@ export const ConsensusAccountDetailsView: FC<ConsensusAccountDetailsViewProps> =
7267
<CopyToClipboard value={account.address} />
7368
</div>
7469
</dd>
70+
{(showLayer || showBalancesOnOtherLayers) && (
71+
<>
72+
<dt>{t('common.chain')}</dt>
73+
<dd className="inline!">
74+
<DashboardLink scope={account} />
75+
{showBalancesOnOtherLayers && <BalancesOnOtherLayers account={account} />}
76+
</dd>
77+
</>
78+
)}
7579
<dt>{t('account.totalBalance')}</dt>
7680
<dd>
7781
<div className="w-full max-w-[25ex] text-right">

src/app/components/Account/RuntimeAccountDetailsView.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { CardEmptyState } from '../CardEmptyState'
2323
import { extractMinimalProxyERC1167 } from '../ContractVerificationIcon/extractMinimalProxyERC1167'
2424
import { AbiPlaygroundLink } from '../ContractVerificationIcon/AbiPlaygroundLink'
2525
import { transactionsContainerId } from '../../utils/tabAnchors'
26+
import { BalancesOnOtherLayers } from './BalancesOnOtherLayers'
2627

2728
type RuntimeAccountDetailsViewProps = {
2829
isLoading?: boolean
@@ -31,6 +32,7 @@ type RuntimeAccountDetailsViewProps = {
3132
token?: EvmToken
3233
tokenPrices: AllTokenPrices
3334
showLayer?: boolean
35+
showBalancesOnOtherLayers?: boolean
3436
}
3537

3638
export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
@@ -40,6 +42,7 @@ export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
4042
isError,
4143
tokenPrices,
4244
showLayer,
45+
showBalancesOnOtherLayers,
4346
}) => {
4447
const { t } = useTranslation()
4548

@@ -59,14 +62,6 @@ export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
5962

6063
return (
6164
<StyledDescriptionList>
62-
{showLayer && (
63-
<>
64-
<dt>{t('common.paratime')}</dt>
65-
<dd>
66-
<DashboardLink scope={account} />
67-
</dd>
68-
</>
69-
)}
7065
<StyledListTitleWithAvatar>
7166
<AccountAvatar account={account} />
7267
</StyledListTitleWithAvatar>
@@ -90,6 +85,16 @@ export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
9085
</>
9186
)}
9287

88+
{(showLayer || showBalancesOnOtherLayers) && (
89+
<>
90+
<dt>{t('common.paratime')}</dt>
91+
<dd className="inline!">
92+
<DashboardLink scope={account} />
93+
{showBalancesOnOtherLayers && <BalancesOnOtherLayers account={account} />}
94+
</dd>
95+
</>
96+
)}
97+
9398
{contract && (
9499
<>
95100
<dt>{t('contract.verification.title')}</dt>
@@ -130,7 +135,7 @@ export const RuntimeAccountDetailsView: FC<RuntimeAccountDetailsViewProps> = ({
130135

131136
<dt>{t('common.balance')}</dt>
132137
<dd>
133-
<RuntimeBalanceDisplay balances={account.balances} />
138+
<RuntimeBalanceDisplay balances={account.balances} scope={account} />
134139
</dd>
135140

136141
<dt>{t('common.tokens')}</dt>

src/app/components/Balance/RuntimeBalanceDisplay.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import { FC } from 'react'
22
import { RuntimeSdkBalance } from '../../../oasis-nexus/api'
3-
import { useTranslation } from 'react-i18next'
43
import { RoundedBalance } from '../RoundedBalance'
4+
import { getTokensForScope } from '../../../config'
5+
import { RuntimeScope } from '../../../types/searchScope'
6+
7+
export const RuntimeBalanceDisplay: FC<{
8+
scope: RuntimeScope
9+
balances: RuntimeSdkBalance[] | undefined
10+
className?: string
11+
}> = ({ scope, balances = [], className = '' }) => {
12+
const balancesOrZero =
13+
balances.length === 0 || balances[0].balance === undefined
14+
? [{ balance: '0', token_symbol: getTokensForScope(scope)[0].ticker }]
15+
: balances
516

6-
export const RuntimeBalanceDisplay: FC<{ balances: RuntimeSdkBalance[] | undefined }> = ({
7-
balances = [],
8-
}) => {
9-
const { t } = useTranslation()
10-
if (balances.length === 0 || balances[0].balance === undefined) {
11-
return t('common.missing')
12-
}
1317
return (
14-
<div>
15-
{balances.map(balance => (
18+
<div className={className}>
19+
{balancesOrZero.map(balance => (
1620
<div key={balance.token_symbol}>
1721
<RoundedBalance value={balance.balance} ticker={balance.token_symbol} />
1822
</div>

src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountDetailsCard.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ export const ConsensusAccountDetailsCard: FC<ConsensusAccountDetailsCardProps> =
1919

2020
return (
2121
<SubPageCard featured isLoadingTitle={isLoading} title={t('account.title')} mainTitle>
22-
<ConsensusAccountDetailsView isError={isError} isLoading={isLoading} account={account} />
22+
<ConsensusAccountDetailsView
23+
isError={isError}
24+
isLoading={isLoading}
25+
account={account}
26+
showBalancesOnOtherLayers
27+
/>
2328
</SubPageCard>
2429
)
2530
}

src/app/pages/RuntimeAccountDetailsPage/RuntimeAccountDetailsCard.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const RuntimeAccountDetailsCard: FC<RuntimeAccountDetailsProps> = ({
3636
account={account}
3737
token={token}
3838
tokenPrices={tokenPrices}
39+
showBalancesOnOtherLayers={!isContract}
3940
/>
4041
</SubPageCard>
4142
)

src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export const TokenDetailsCard: FC<{
106106

107107
<dt>{t('common.balance')} </dt>
108108
<dd>
109-
<RuntimeBalanceDisplay balances={account?.balances} />
109+
<RuntimeBalanceDisplay balances={account?.balances} scope={account} />
110110
</dd>
111111

112112
<dt>{t('tokens.totalSupply')}</dt>

src/locales/en/translation.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"account": {
33
"active": "Active",
44
"available": "Available",
5+
"availableBalance": "Available balance",
56
"balanceDistribution": "Balance Distribution",
67
"cantLoadDetails": "Unfortunately we couldn't load the account details at this time. Please try again later.",
78
"debonding": "Debonding",
@@ -13,6 +14,7 @@
1314
"firstActivity": "First activity",
1415
"ERC20": "ERC-20",
1516
"ERC721": "ERC-721",
17+
"hasBalancesOnOtherLayers": "this account also has transactions on",
1618
"listTitle": "Accounts",
1719
"namedByOasis": "Name appointed by Oasis",
1820
"namedByDeltaDao": "Identified by deltaDAO",
@@ -79,6 +81,7 @@
7981
"details": "Details",
8082
"emerald": "Emerald",
8183
"epoch": "Epoch",
84+
"chain": "Chain",
8285
"cipher": "Cipher",
8386
"consensus": "Consensus",
8487
"eth": "ETH",
@@ -99,7 +102,6 @@
99102
"hide": "Hide",
100103
"id": "ID",
101104
"invalidVotes": "Invalid votes",
102-
"layer": "Layer",
103105
"localnet": "Localnet",
104106
"loadMore": "Load more",
105107
"lessThanAmount": "&lt;{{value, number}} <TickerLink />",

0 commit comments

Comments
 (0)