mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
Celo Account info on Address details page (#2966)
* Celo Account info on Address details page Fixes #2962 * add signers information and change hints placement
This commit is contained in:
@@ -20,6 +20,7 @@ export interface Address extends UserTags {
|
||||
ens_domain_name: string | null;
|
||||
filecoin?: AddressFilecoinParams;
|
||||
zilliqa?: AddressZilliqaParams;
|
||||
celo?: AddressCeloParams;
|
||||
// TODO: if we are happy with tabs-counters method, should we delete has_something fields?
|
||||
has_beacon_chain_withdrawals?: boolean;
|
||||
has_logs: boolean;
|
||||
@@ -40,6 +41,19 @@ export interface AddressZilliqaParams {
|
||||
is_scilla_contract: boolean;
|
||||
}
|
||||
|
||||
export interface AddressCeloParams {
|
||||
account: {
|
||||
locked_celo: string;
|
||||
metadata_url: string | null;
|
||||
name: string | null;
|
||||
nonvoting_locked_celo: string;
|
||||
type: string;
|
||||
vote_signer_address: AddressParam | null;
|
||||
validator_signer_address: AddressParam | null;
|
||||
attestation_signer_address: AddressParam | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface AddressCounters {
|
||||
transactions_count: string;
|
||||
token_transfers_count: string;
|
||||
|
||||
@@ -23,6 +23,7 @@ import Address3rdPartyWidgets from './Address3rdPartyWidgets';
|
||||
import useAddress3rdPartyWidgets from './address3rdPartyWidgets/useAddress3rdPartyWidgets';
|
||||
import AddressAlternativeFormat from './details/AddressAlternativeFormat';
|
||||
import AddressBalance from './details/AddressBalance';
|
||||
import AddressCeloAccount from './details/AddressCeloAccount';
|
||||
import AddressImplementations from './details/AddressImplementations';
|
||||
import AddressNameInfo from './details/AddressNameInfo';
|
||||
import AddressNetWorth from './details/AddressNetWorth';
|
||||
@@ -62,6 +63,7 @@ const AddressDetails = ({ addressQuery, countersQuery, isLoading }: Props) => {
|
||||
has_token_transfers: true,
|
||||
has_validated_blocks: false,
|
||||
filecoin: undefined,
|
||||
celo: undefined,
|
||||
creator_filecoin_robust_address: null,
|
||||
creator_address_hash: null,
|
||||
}), [ addressHash ]);
|
||||
@@ -90,6 +92,11 @@ const AddressDetails = ({ addressQuery, countersQuery, isLoading }: Props) => {
|
||||
<>
|
||||
{ addressQuery.isDegradedData && <ServiceDegradationWarning isLoading={ isLoading } mb={ 6 }/> }
|
||||
<DetailedInfo.Container>
|
||||
|
||||
{ data.celo?.account && (
|
||||
<AddressCeloAccount data={ data.celo.account } isLoading={ isLoading }/>
|
||||
) }
|
||||
|
||||
<AddressAlternativeFormat isLoading={ isLoading } addressHash={ addressHash }/>
|
||||
|
||||
{ data.filecoin?.id && (
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
|
||||
import * as addressMock from 'mocks/address/address';
|
||||
import { test, expect } from 'playwright/lib';
|
||||
import { Container } from 'ui/shared/DetailedInfo/DetailedInfo';
|
||||
|
||||
import AddressCeloAccount from './AddressCeloAccount';
|
||||
|
||||
const DATA = {
|
||||
name: 'CLabs Validator #2 on alfajores',
|
||||
type: 'validator',
|
||||
locked_celo: '10000000000000000000000',
|
||||
// eslint-disable-next-line max-len
|
||||
metadata_url: 'https://storage.googleapis.com/clabs_validator_metadata/alfajores/validator-alfajores-0x050f34537F5b2a00B9B9C752Cb8500a3fcE3DA7d-metadata.json',
|
||||
nonvoting_locked_celo: '10000000000000000000000',
|
||||
vote_signer_address: addressMock.withName,
|
||||
validator_signer_address: addressMock.withEns,
|
||||
attestation_signer_address: addressMock.withoutName,
|
||||
};
|
||||
|
||||
test('default view +@mobile', async({ render }) => {
|
||||
const component = await render(
|
||||
<Container>
|
||||
<AddressCeloAccount data={ DATA }/>
|
||||
</Container>,
|
||||
);
|
||||
await component.getByText('View details').click();
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
import { Grid, GridItem } from '@chakra-ui/react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { upperFirst } from 'es-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import type { Address } from 'types/api/address';
|
||||
import type { ExcludeNull, ExcludeUndefined } from 'types/utils';
|
||||
|
||||
import config from 'configs/app';
|
||||
import { currencyUnits } from 'lib/units';
|
||||
import { CollapsibleDetails } from 'toolkit/chakra/collapsible';
|
||||
import { Link } from 'toolkit/chakra/link';
|
||||
import { Hint } from 'toolkit/components/Hint/Hint';
|
||||
import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import TruncatedValue from 'ui/shared/TruncatedValue';
|
||||
|
||||
const AddressCeloAccountItem = ({ label, hint, children }: { label: string; hint: string; children: React.ReactNode }) => {
|
||||
return (
|
||||
<>
|
||||
<GridItem color="text.secondary" display="flex" alignItems="center">
|
||||
<Hint label={ hint } boxSize={ 4 } mr={ 1 }/>
|
||||
<TruncatedValue value={ label } maxW={{ base: '130px', lg: 'unset' }}/>
|
||||
</GridItem>
|
||||
{ children }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
interface Props {
|
||||
isLoading?: boolean;
|
||||
data: ExcludeNull<ExcludeUndefined<Address['celo']>['account']>;
|
||||
}
|
||||
|
||||
const AddressCeloAccount = ({ isLoading, data }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<DetailedInfo.ItemLabel
|
||||
hint="Celo account info (from the Accounts contract), including it's human-readable name"
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
Celo account
|
||||
</DetailedInfo.ItemLabel>
|
||||
<DetailedInfo.ItemValue multiRow>
|
||||
{ data.name && <TruncatedValue value={ data.name } mr={ 3 }/> }
|
||||
<CollapsibleDetails noScroll variant="secondary" display="block" textStyle={ undefined } fontSize="sm" loading={ isLoading }>
|
||||
<Grid
|
||||
gridTemplateColumns="max-content minmax(0px, 1fr)"
|
||||
textStyle="sm"
|
||||
bgColor={{ _light: 'blackAlpha.50', _dark: 'whiteAlpha.50' }}
|
||||
w="100%"
|
||||
p={{ base: 2, lg: 3 }}
|
||||
mt={ 1 }
|
||||
columnGap={ 3 }
|
||||
rowGap={ 4 }
|
||||
borderBottomRightRadius="base"
|
||||
borderBottomLeftRadius="base"
|
||||
>
|
||||
<AddressCeloAccountItem label="Type" hint="The role of the account: regular, validator, or validator group">
|
||||
{ upperFirst(data.type) }
|
||||
</AddressCeloAccountItem>
|
||||
|
||||
{ data.metadata_url && (
|
||||
<AddressCeloAccountItem label="Metadata URL" hint="Link to additional information published by the account owner">
|
||||
<Link href={ data.metadata_url } external>
|
||||
<TruncatedValue value={ data.metadata_url }/>
|
||||
</Link>
|
||||
</AddressCeloAccountItem>
|
||||
) }
|
||||
|
||||
<AddressCeloAccountItem
|
||||
label={ `Locked ${ currencyUnits.ether }` }
|
||||
hint="Total amount of CELO locked by this account (used for staking or governance)"
|
||||
>
|
||||
<TruncatedValue value={ BigNumber(data.locked_celo).div(10 ** config.chain.currency.decimals).toFormat() }/>
|
||||
</AddressCeloAccountItem>
|
||||
|
||||
<AddressCeloAccountItem
|
||||
label={ `Non-voting locked ${ currencyUnits.ether }` }
|
||||
hint="Portion of locked CELO that is not currently used for voting"
|
||||
>
|
||||
<TruncatedValue value={ BigNumber(data.nonvoting_locked_celo).div(10 ** config.chain.currency.decimals).toFormat() }/>
|
||||
</AddressCeloAccountItem>
|
||||
|
||||
{ data.vote_signer_address && (
|
||||
<AddressCeloAccountItem
|
||||
label="Vote signer address"
|
||||
hint="Address authorized to vote in governance and validator elections on behalf of this account"
|
||||
>
|
||||
<AddressEntity address={ data.vote_signer_address }/>
|
||||
</AddressCeloAccountItem>
|
||||
) }
|
||||
|
||||
{ data.validator_signer_address && (
|
||||
<AddressCeloAccountItem
|
||||
label="Validator signer address"
|
||||
hint="Address authorized to manage a validator or validator group and sign consensus messages for this account"
|
||||
>
|
||||
<AddressEntity address={ data.validator_signer_address }/>
|
||||
</AddressCeloAccountItem>
|
||||
) }
|
||||
|
||||
{ data.attestation_signer_address && (
|
||||
<AddressCeloAccountItem
|
||||
label="Attestation signer address"
|
||||
hint="Address whose key this account uses to sign attestations on the Attestations contract"
|
||||
>
|
||||
<AddressEntity address={ data.attestation_signer_address }/>
|
||||
</AddressCeloAccountItem>
|
||||
) }
|
||||
</Grid>
|
||||
</CollapsibleDetails>
|
||||
</DetailedInfo.ItemValue>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(AddressCeloAccount);
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
@@ -323,6 +323,16 @@ const AddressPageContent = () => {
|
||||
const tags: Array<EntityTag> = React.useMemo(() => {
|
||||
return [
|
||||
...(addressQuery.data?.public_tags?.map((tag) => ({ slug: tag.label, name: tag.display_name, tagType: 'custom' as const, ordinal: -1 })) || []),
|
||||
addressQuery.data?.celo?.account ? {
|
||||
slug: 'celo-account',
|
||||
name: 'Celo account',
|
||||
tagType: 'custom' as const,
|
||||
ordinal: PREDEFINED_TAG_PRIORITY,
|
||||
meta: {
|
||||
bgColor: 'yellow.200',
|
||||
textColor: 'black',
|
||||
},
|
||||
} : undefined,
|
||||
!addressQuery.data?.is_contract ? { slug: 'eoa', name: 'EOA', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } : undefined,
|
||||
config.features.validators.isEnabled && addressQuery.data?.has_validated_blocks ?
|
||||
{ slug: 'validator', name: 'Validator', tagType: 'custom' as const, ordinal: PREDEFINED_TAG_PRIORITY } :
|
||||
|
||||
Reference in New Issue
Block a user