Skip to content

Commit

Permalink
filecoin addresses support
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Nov 1, 2024
1 parent 1aaae10 commit 1a0f0f9
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 9 deletions.
9 changes: 9 additions & 0 deletions mocks/address/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,12 @@ export const validator: Address = {
watchlist_address_id: null,
ens_domain_name: null,
};

export const filecoin = {
...validator,
filecoin: {
actor_type: 'evm' as const,
id: 'f02977693',
robust: 'f410fuiwj6a3yxajbohrl5vu6ns6o2e2jriul52lvzci',
},
};
25 changes: 25 additions & 0 deletions types/api/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface Address extends UserTags {
creation_tx_hash: string | null;
exchange_rate: string | null;
ens_domain_name: string | null;
filecoin?: AddressFilecoinParams;
// TODO: if we are happy with tabs-counters method, should we delete has_something fields?
has_beacon_chain_withdrawals?: boolean;
has_decompiled_code: boolean;
Expand Down Expand Up @@ -268,3 +269,27 @@ export type AddressEpochRewardsItem = {
epoch_number: number;
associated_account: AddressParam;
}

export type AddressFilecoinParams = {
actor_type: FilecoinActorType;
id: string;
robust: string;
}

export type FilecoinActorType =
'account' |
'cron' |
'datacap' |
'eam' |
'ethaccount' |
'evm' |
'init' |
'market' |
'miner' |
'multisig' |
'paych' |
'placeholder' |
'power' |
'reward' |
'system' |
'verifreg';
2 changes: 2 additions & 0 deletions types/api/addressParams.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { AddressFilecoinParams } from './address';
import type { AddressMetadataTagApi } from './addressMetadata';

export interface AddressImplementation {
Expand Down Expand Up @@ -33,6 +34,7 @@ export type AddressParamBasic = {
reputation: number | null;
tags: Array<AddressMetadataTagApi>;
} | null;
filecoin?: AddressFilecoinParams;
}

export type AddressParam = UserTags & AddressParamBasic;
23 changes: 23 additions & 0 deletions ui/address/AddressDetails.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ test.describe('mobile', () => {
});
});

test('filecoin', async({ render, mockApiResponse, page }) => {
await mockApiResponse('address', addressMock.filecoin, { pathParams: { hash: ADDRESS_HASH } });
await mockApiResponse('address_counters', countersMock.forValidator, { pathParams: { hash: ADDRESS_HASH } });

const component = await render(<AddressDetails addressQuery={{ data: addressMock.filecoin } as AddressQuery}/>, { hooksConfig });

await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
});

test('contract', async({ render, page, mockApiResponse }) => {
Expand Down Expand Up @@ -92,3 +103,15 @@ test('validator', async({ render, mockApiResponse, page }) => {
maskColor: pwConfig.maskColor,
});
});

test('filecoin', async({ render, mockApiResponse, page }) => {
await mockApiResponse('address', addressMock.filecoin, { pathParams: { hash: ADDRESS_HASH } });
await mockApiResponse('address_counters', countersMock.forValidator, { pathParams: { hash: ADDRESS_HASH } });

const component = await render(<AddressDetails addressQuery={{ data: addressMock.filecoin } as AddressQuery}/>, { hooksConfig });

await expect(component).toHaveScreenshot({
mask: [ page.locator(pwConfig.adsBannerSelector) ],
maskColor: pwConfig.maskColor,
});
});
47 changes: 47 additions & 0 deletions ui/address/AddressDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ import getQueryParamString from 'lib/router/getQueryParamString';
import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';

import AddressBalance from './details/AddressBalance';
import AddressImplementations from './details/AddressImplementations';
import AddressNameInfo from './details/AddressNameInfo';
import AddressNetWorth from './details/AddressNetWorth';
import AddressSaveOnGas from './details/AddressSaveOnGas';
import FilecoinActorTag from './filecoin/FilecoinActorTag';
import TokenSelect from './tokenSelect/TokenSelect';
import useAddressCountersQuery from './utils/useAddressCountersQuery';
import type { AddressQuery } from './utils/useAddressQuery';
Expand Down Expand Up @@ -63,6 +66,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
has_tokens: true,
has_token_transfers: true,
has_validated_blocks: false,
filecoin: undefined,
}), [ addressHash ]);

// error handling (except 404 codes)
Expand Down Expand Up @@ -91,6 +95,49 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
rowGap={{ base: 1, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden"
>
{ data.filecoin?.id && (
<>
<DetailsInfoItem.Label
hint="Short identifier of an address that may change with chain state updates"
>
ID
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
<Text>{ data.filecoin.id }</Text>
<CopyToClipboard text={ data.filecoin.id }/>
</DetailsInfoItem.Value>
</>
) }

{ data.filecoin?.actor_type && (
<>
<DetailsInfoItem.Label
hint="Identifies the purpose and behavior of the address on the Filecoin network"
>
Actor
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
<FilecoinActorTag actorType={ data.filecoin.actor_type }/>
</DetailsInfoItem.Value>
</>
) }

{ (data.filecoin?.actor_type === 'evm' || data.filecoin?.actor_type === 'ethaccount') && data?.filecoin?.robust && (
<>
<DetailsInfoItem.Label
hint="0x-style address to which the Filecoin address is assigned by the Ethereum Address Manager"
>
Ethereum Address
</DetailsInfoItem.Label>
<DetailsInfoItem.Value flexWrap="nowrap">
<Box overflow="hidden">
<HashStringShortenDynamic hash={ data.hash }/>
</Box>
<CopyToClipboard text={ data.hash }/>
</DetailsInfoItem.Value>
</>
) }

<AddressNameInfo data={ data } isLoading={ addressQuery.isPlaceholderData }/>

{ data.is_contract && data.creation_tx_hash && data.creator_address_hash && (
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions ui/address/filecoin/FilecoinActorTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Tag } from '@chakra-ui/react';
import React from 'react';

import type { FilecoinActorType } from 'types/api/address';

const ACTOR_TYPES: Record<FilecoinActorType, string> = {
account: 'Account',
cron: 'Scheduled Tasks',
datacap: 'Data Cap Management',
eam: 'Ethereum Address Manager',
ethaccount: 'Ethereum-Compatible Account',
evm: 'Ethereum Virtual Machine',
init: 'Initialization',
market: 'Storage Market',
miner: 'Storage Provider',
multisig: 'Multi-Signature Wallet',
paych: 'Payment Channel',
placeholder: 'Placeholder Address',
power: 'Power Management',
reward: 'Incentives and Rewards',
system: 'System Operations',
verifreg: 'Verification Registry',
};

type Props = {
actorType: FilecoinActorType;
}

const FilecoinActorTag = ({ actorType }: Props) => {
const text = ACTOR_TYPES[actorType];

if (!text) {
return null;
}

return <Tag colorScheme="gray">{ text }</Tag>;
};

export default FilecoinActorTag;
11 changes: 9 additions & 2 deletions ui/pages/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,14 @@ const AddressPageContent = () => {
/>
) }
<AddressEntity
address={{ ...addressQuery.data, hash: checkSummedHash, name: '', ens_domain_name: '', implementations: null }}
address={{
...addressQuery.data,
hash: checkSummedHash,
filecoin: addressQuery.data?.filecoin,
name: '',
ens_domain_name: '',
implementations: null,
}}
isLoading={ isLoading }
fontFamily="heading"
fontSize="lg"
Expand All @@ -361,7 +368,7 @@ const AddressPageContent = () => {
{ !isLoading && !addressQuery.data?.is_contract && config.features.account.isEnabled && (
<AddressFavoriteButton hash={ hash } watchListId={ addressQuery.data?.watchlist_address_id }/>
) }
<AddressQrCode address={{ hash: checkSummedHash }} isLoading={ isLoading }/>
<AddressQrCode address={{ hash: addressQuery.data?.filecoin?.robust ?? checkSummedHash }} isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading }/>
<HStack ml="auto" gap={ 2 }/>
{ !isLoading && addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled &&
Expand Down
6 changes: 3 additions & 3 deletions ui/shared/entities/address/AddressEntity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const Icon = (props: IconProps) => {
<Flex marginRight={ styles.marginRight }>
<AddressIdenticon
size={ props.size === 'lg' ? 30 : 20 }
hash={ props.address.hash }
hash={ props.address.filecoin?.robust ?? props.address.hash }
/>
</Flex>
);
Expand Down Expand Up @@ -115,7 +115,7 @@ const Content = chakra((props: ContentProps) => {
return (
<EntityBase.Content
{ ...props }
text={ props.address.hash }
text={ props.address.filecoin?.robust ?? props.address.hash }
/>
);
});
Expand All @@ -126,7 +126,7 @@ const Copy = (props: CopyProps) => {
return (
<EntityBase.Copy
{ ...props }
text={ props.address.hash }
text={ props.address.filecoin?.robust ?? props.address.hash }
/>
);
};
Expand Down
4 changes: 2 additions & 2 deletions ui/verifiedContracts/VerifiedContractsListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ const VerifiedContractsListItem = ({ data, isLoading }: Props) => {
{ data.certified && <ContractCertifiedLabel iconSize={ 5 } boxSize={ 5 } mx={ 2 }/> }
</Flex>
<Skeleton isLoaded={ !isLoading } color="text_secondary" ml="auto">
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/>
<HashStringShorten hash={ data.address.filecoin?.robust ?? data.address.hash } isTooltipDisabled/>
</Skeleton>
<CopyToClipboard text={ data.address.hash } isLoading={ isLoading }/>
<CopyToClipboard text={ data.address.filecoin?.robust ?? data.address.hash } isLoading={ isLoading }/>
</Flex>
<Flex columnGap={ 3 }>
<Skeleton isLoaded={ !isLoading } fontWeight={ 500 }>Balance { currencyUnits.ether }</Skeleton>
Expand Down
4 changes: 2 additions & 2 deletions ui/verifiedContracts/VerifiedContractsTableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ const VerifiedContractsTableItem = ({ data, isLoading }: Props) => {
</Flex>
<Flex alignItems="center" ml={ 7 }>
<Skeleton isLoaded={ !isLoading } color="text_secondary" my={ 1 }>
<HashStringShorten hash={ data.address.hash } isTooltipDisabled/>
<HashStringShorten hash={ data.address.filecoin?.robust ?? data.address.hash } isTooltipDisabled/>
</Skeleton>
<CopyToClipboard text={ data.address.hash } isLoading={ isLoading }/>
<CopyToClipboard text={ data.address.filecoin?.robust ?? data.address.hash } isLoading={ isLoading }/>
</Flex>
</Td>
<Td isNumeric>
Expand Down

0 comments on commit 1a0f0f9

Please sign in to comment.